<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/72X72.ico">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/48X48.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/32X32.ico">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"issacyoung.cn","root":"/","scheme":"Pisces","version":"7.7.1","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
<meta property="og:type" content="website">
<meta property="og:title" content="Young‘s River">
<meta property="og:url" content="http://issacyoung.cn/index.html">
<meta property="og:site_name" content="Young‘s River">
<meta property="og:description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="Issac Young">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="http://issacyoung.cn/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome: true,
    isPost: false
  };
</script>

  <title>Young‘s River</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="Young‘s River" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <div>
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Young‘s River</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
        <p class="site-subtitle">一个正能量的程序员，喜欢码字，热爱运动，向往自由</p>
  </div>

  <div class="site-nav-right"></div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档</a>

  </li>
  </ul>

</nav>
</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

  <a href="https://github.com/IssacYoung2013" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content">
            

  <div class="posts-expand">
        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2024/04/21/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8Bjava%E5%B8%B8%E8%A7%81%E5%9D%91/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2024/04/21/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8Bjava%E5%B8%B8%E8%A7%81%E5%9D%91/" class="post-title-link" itemprop="url">一步一步之java常见坑</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2024-04-21 23:23:26 / 修改时间：23:24:06" itemprop="dateCreated datePublished" datetime="2024-04-21T23:23:26+08:00">2024-04-21</time>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>9.2k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="空指针如何避免"><a href="#空指针如何避免" class="headerlink" title="空指针如何避免"></a>空指针如何避免</h3><p>对象没有初始化直接使用</p>
<h4 id="赋值时自动拆箱出现空指针"><a href="#赋值时自动拆箱出现空指针" class="headerlink" title="赋值时自动拆箱出现空指针"></a>赋值时自动拆箱出现空指针</h4><p>为什么需要包装器类型？</p>
<p>为了让基本类型具有对象的性质，可以让容器 Collection 中使用。</p>
<ul>
<li><p>变量赋值自动拆箱出现</p>
</li>
<li><p>方法传参自动拆箱出现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UnboxingNpe</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">add</span><span class="params">(<span class="keyword">int</span> x,<span class="keyword">int</span> y)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> x + y;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">compare</span><span class="params">(<span class="keyword">long</span> x, <span class="keyword">long</span> y)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> x &gt;= y;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 1. 变量赋值自动拆箱出现的空指针</span></span><br><span class="line">        <span class="comment">// javac UnboxingNpe.java</span></span><br><span class="line">        <span class="comment">// javap -c UnboxingNpe.class 反编译汇编</span></span><br><span class="line">        <span class="comment">// 发现 long count_ 调用了 Long.longValue 方法</span></span><br><span class="line"><span class="comment">//        Long count = null;</span></span><br><span class="line"><span class="comment">//        long count_ = count;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 2. 方法传参自动拆箱出现的空指针</span></span><br><span class="line"><span class="comment">//        Integer left = null;</span></span><br><span class="line"><span class="comment">//        Integer right = null;</span></span><br><span class="line"><span class="comment">//        System.out.println(add(left,right));</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 3. 用于大小比较的场景</span></span><br><span class="line">        Long left = <span class="number">10L</span>;</span><br><span class="line">        Long right = <span class="keyword">null</span>;</span><br><span class="line">        System.out.println(compare(left,right));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ul>
<h5 id="建议"><a href="#建议" class="headerlink" title="建议"></a>建议</h5><ul>
<li>基于数据类型优先包装器类型，优先使用基本类型</li>
<li>对于不确定的包装器类型，一定要校验是否为NULL</li>
<li>对于值NULL的包装器类型，赋值为0</li>
</ul>
<h4 id="字符串、数组、集合-N-P-E"><a href="#字符串、数组、集合-N-P-E" class="headerlink" title="字符串、数组、集合 N P E"></a>字符串、数组、集合 N P E</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BasicUsageNpe</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">boolean</span> <span class="title">stringEquals</span><span class="params">(String x, String y)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// java 比较字符串不能使用==；遵循常量.equals变量</span></span><br><span class="line">        <span class="keyword">return</span> x.equals(y);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">User</span> </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> String name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 1. 字符串使用equal</span></span><br><span class="line"><span class="comment">//        System.out.println(stringEquals("xyz", null));</span></span><br><span class="line"><span class="comment">//        System.out.println(stringEquals(null, "xyz"));</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 2. 对象数组 new 出来，但是元素没有初始化</span></span><br><span class="line">        User[] users = <span class="keyword">new</span> User[<span class="number">10</span>];</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i != <span class="number">10</span>; ++i) &#123;</span><br><span class="line">            users[i] = <span class="keyword">new</span> User();</span><br><span class="line">            users[i].name = <span class="string">"issac-"</span> + i;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 3. List 对象 allAll 传递 null</span></span><br><span class="line">        List&lt;User&gt; userList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        User user = <span class="keyword">null</span>;</span><br><span class="line">        List&lt;User&gt; users_ = <span class="keyword">null</span>;</span><br><span class="line">        userList.add(user);</span><br><span class="line">        userList.addAll(users_);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="Optional-空指针"><a href="#Optional-空指针" class="headerlink" title="Optional 空指针"></a>Optional 空指针</h4><p>代表一个值存在不存在，java8之前用null表示不存在，可以看作至多包含一个元素的集合</p>
<ul>
<li>与直接判断是否为null无区别</li>
<li>认识到 orElse 、get 的妙用</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">OptionalUsage</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">User</span> </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> String name;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> name;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">isUserEqualNull</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        User user = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">if</span> (user != <span class="keyword">null</span>) &#123;</span><br><span class="line">            System.out.println(<span class="string">"User is not null"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">"User is null"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        Optional&lt;User&gt; optional = Optional.empty();</span><br><span class="line">        <span class="keyword">if</span> (optional.isPresent()) &#123;</span><br><span class="line">            System.out.println(<span class="string">"User is not null"</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">"User is null"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> User <span class="title">anoymos</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> User();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 没有意义的使用方法</span></span><br><span class="line">        isUserEqualNull();</span><br><span class="line"></span><br><span class="line">        User user = <span class="keyword">null</span>;</span><br><span class="line">        Optional&lt;User&gt; optionalUser = Optional.ofNullable(<span class="keyword">null</span>);</span><br><span class="line">        <span class="comment">// 存在及返回</span></span><br><span class="line">        optionalUser.orElse(<span class="keyword">new</span> User());</span><br><span class="line">        <span class="comment">// 存在则返回 空则由函数产生新的对象，复用性更强</span></span><br><span class="line">        optionalUser.orElseGet(() -&gt; anoymos());</span><br><span class="line">        <span class="comment">// 存在即返回 否则抛出异常</span></span><br><span class="line">        optionalUser.orElseThrow(RuntimeException::<span class="keyword">new</span>);</span><br><span class="line">        <span class="comment">// 存在才去做相应的处理</span></span><br><span class="line">        optionalUser.ifPresent(u-&gt; System.out.println(u.getName()));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// map 可以对Optional中的对象执行某种操作 且会返回一个 Optional对象</span></span><br><span class="line">        optionalUser.map(u-&gt;u.getName()).orElse(<span class="string">"anymos"</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// map 可以无限级联操作</span></span><br><span class="line">        optionalUser.map(u-&gt;u.getName()).map(name-&gt;name.length()).orElse(<span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="try-catch没有解决问题"><a href="#try-catch没有解决问题" class="headerlink" title="try-catch没有解决问题"></a>try-catch没有解决问题</h4><p>exception 意外、例外。</p>
<ul>
<li>使用异常，而不是返回码（或类似），因为异常会更加详细</li>
<li>主动捕获检查性异常，并对异常信息进行返回</li>
<li>保持代码整洁，一个方法不要有多个 try catch 或者嵌套的 try catch</li>
<li>捕获更加具体的异常，而不是通用的 Exception</li>
<li>合理的设计自定义的异常类</li>
</ul>
<h4 id="编码中常见的异常"><a href="#编码中常见的异常" class="headerlink" title="编码中常见的异常"></a>编码中常见的异常</h4><h3 id="数值计算"><a href="#数值计算" class="headerlink" title="数值计算"></a>数值计算</h3><h4 id="BigDecimal"><a href="#BigDecimal" class="headerlink" title="BigDecimal"></a>BigDecimal</h4><p>精确计算的类，核心是精度，精度如果不匹配，结果大概率不会符合预期</p>
<ul>
<li>初始化设置精度</li>
<li>除法除不尽设置精度</li>
<li>比较用compare </li>
</ul>
<h4 id="SimpleDateFormat-常用的坑"><a href="#SimpleDateFormat-常用的坑" class="headerlink" title="SimpleDateFormat 常用的坑"></a>SimpleDateFormat 常用的坑</h4><ul>
<li>可以解析大于/等于它时间精度的日期</li>
<li>线程不安全<ul>
<li>定义为局部变量</li>
<li>使用 ThreadLocal</li>
<li>使用 synchronize 不推荐</li>
</ul>
</li>
</ul>
<h4 id="for循环"><a href="#for循环" class="headerlink" title="for循环"></a>for循环</h4><ul>
<li>如果是数组，有多余的索引</li>
<li>for-each 优于 for，任何实现 Iterable 接口的对象都可以使用</li>
</ul>
<h4 id="不好好判等，集合存储就会乱套"><a href="#不好好判等，集合存储就会乱套" class="headerlink" title="不好好判等，集合存储就会乱套"></a>不好好判等，集合存储就会乱套</h4><ul>
<li>Object 的 equals 和 hashcode 方法<ul>
<li>默认的 equals 对象地址，hashcode 根据对象地址生成一个整数值</li>
<li>只重写 equals 方法的问题</li>
</ul>
</li>
<li>集合中的元素的索引竟然也与 equals 方法相关<ul>
<li>类实现了compareTo 方法 就需要实现equals</li>
<li>compareTo 与 equals 实现过程需要一致</li>
</ul>
</li>
</ul>
<h4 id="使用lombok-注解没有达到预期"><a href="#使用lombok-注解没有达到预期" class="headerlink" title="使用lombok 注解没有达到预期"></a>使用lombok 注解没有达到预期</h4><ul>
<li><p>常用注解</p>
<ul>
<li>@Getter @Setter</li>
<li>@ToString</li>
<li>@Data<ul>
<li>setter getter equals canEqual hashCode toString</li>
</ul>
</li>
<li>@NoArgsContructor</li>
<li>@Sl4j</li>
</ul>
</li>
<li><p>Source.java  抽象语法树（AST） Target.ava </p>
</li>
<li><p>单字母的小写第二个字母大写会转成一个单词，编写代码不符合规范</p>
</li>
</ul>
<h4 id="避免抽象类和接口的选择失误"><a href="#避免抽象类和接口的选择失误" class="headerlink" title="避免抽象类和接口的选择失误"></a>避免抽象类和接口的选择失误</h4><ul>
<li><p>设计 Worker</p>
<ul>
<li>工作、行为拆分为抽象类合适吗？不合适</li>
<li>工作、行为拆分为接口合理吗？不合理</li>
</ul>
</li>
<li><p>抽象类、接口的含义和特性</p>
<ul>
<li>抽象类是子类的通用特性，包含属性和行为；接口是定义行为，并不关心谁去实现</li>
<li>抽象类是对类本质的抽象，表达的是is-a的关系；接口是对行为的抽象，表达的是 like a 的关系</li>
</ul>
</li>
<li><p>抽象类、接口的相同点</p>
</li>
</ul>
<h4 id="函数式接口和lambda表达式"><a href="#函数式接口和lambda表达式" class="headerlink" title="函数式接口和lambda表达式"></a>函数式接口和lambda表达式</h4><ul>
<li><p>匿名内部类使用lambda表达式代替</p>
<ul>
<li>@FunctionInterface 有且只有一个抽象类接口</li>
</ul>
</li>
<li><p>不熟悉中间操作和结束操作引发的语法错误</p>
</li>
</ul>
<h3 id="反射、泛型"><a href="#反射、泛型" class="headerlink" title="反射、泛型"></a>反射、泛型</h3><h4 id="实现了-Serializable-接口却报错"><a href="#实现了-Serializable-接口却报错" class="headerlink" title="实现了 Serializable 接口却报错"></a>实现了 Serializable 接口却报错</h4><ul>
<li>子类实现了序列化接口，父类没实现，子类可以序列化，父类必须有无参构造函数</li>
<li>类中存在引用对象，那么，这个类对象必须都是可序列化的</li>
<li>同一个对象多次序列化（之间有属性更新），会影响结果吗</li>
</ul>
<h4 id="泛型不仅仅是规定集合中类型"><a href="#泛型不仅仅是规定集合中类型" class="headerlink" title="泛型不仅仅是规定集合中类型"></a>泛型不仅仅是规定集合中类型</h4><ul>
<li><p>泛型就是参数化类型，将类型原来的具体类型参数化</p>
</li>
<li><p>能够不创建新类型的情况下，通过泛型指定不同类型控制形参</p>
</li>
<li><p>特性</p>
<ul>
<li><p>先检查再编译</p>
</li>
<li><p>不支持继承</p>
</li>
<li><p>不能是基本类型</p>
</li>
<li><p>泛型方法参数只能类类型，不能是简单类型</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> &lt;T&gt; <span class="function"><span class="keyword">void</span> <span class="title">doSomething</span><span class="params">(T... values)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (T value : values) &#123;</span><br><span class="line">        System.out.println(value);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception</span>&#123;</span><br><span class="line">    Integer[] ints1 = <span class="keyword">new</span> Integer[]&#123;<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>&#125;;</span><br><span class="line">    <span class="keyword">int</span>[] ints2 = <span class="keyword">new</span> <span class="keyword">int</span>[] &#123;<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,&#125;;</span><br><span class="line"></span><br><span class="line">    doSomething(ints1);</span><br><span class="line">    System.out.println(<span class="string">"------------------------------"</span>);</span><br><span class="line">    doSomething(ints2);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ul>
</li>
</ul>
<h4 id="切记不要使用原始类型"><a href="#切记不要使用原始类型" class="headerlink" title="切记不要使用原始类型"></a>切记不要使用原始类型</h4><ul>
<li>初步优化，指定 <code>List&lt;Object&gt;</code>，明确告诉编译器可以存储任意对象</li>
</ul>
<h4 id="反射"><a href="#反射" class="headerlink" title="反射"></a>反射</h4><ul>
<li><p>允许运行中 java 获取自身信息，并可以操作类或对象的内部属性</p>
</li>
<li><p>应用场景</p>
<ul>
<li>开发通用框架，动态加载需要的对象</li>
<li>动态代理</li>
<li>注解</li>
<li>可扩展性功能</li>
</ul>
</li>
<li><p>缺陷</p>
<ul>
<li>性能开销</li>
<li>破坏封装性</li>
<li>内部曝光</li>
</ul>
</li>
<li><p>类加载过程</p>
<ul>
<li>编译 java文件 - java编译器 - Class 文件</li>
<li>加载与运行 JVM 类加载器、执行引擎</li>
</ul>
</li>
<li><p>Method类</p>
<ul>
<li>getMethod</li>
<li>getDeclaredMethod</li>
<li>getMethods</li>
<li>getDeclaredMethods</li>
</ul>
</li>
<li><p>什么场景获取不到Method</p>
<ul>
<li><p>方法定义基本类型参数，获取方法也必须指定基本类型</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">numeric</span><span class="params">(<span class="keyword">int</span> age)</span> </span>&#123;</span><br><span class="line">    return Boss.class.getName() + ": " + age;</span><br><span class="line">&#125;</span><br><span class="line">Method numeric = clz.getMethod(<span class="string">"numeric"</span>, <span class="keyword">int</span><span class="class">.<span class="keyword">class</span>)</span>;</span><br></pre></td></tr></table></figure>
</li>
<li><p>getDeclaredMethod 不能从当前类获取到父类的方法</p>
</li>
</ul>
</li>
</ul>
<h4 id="并不是所有字符串拼接都用-StringBuilder"><a href="#并不是所有字符串拼接都用-StringBuilder" class="headerlink" title="并不是所有字符串拼接都用 StringBuilder"></a>并不是所有字符串拼接都用 StringBuilder</h4><ul>
<li><p>使用 <code>+</code> 去拼接字符串，会造成怎样的性能损失</p>
<ul>
<li>空间浪费 每次拼接都会创建新对象</li>
<li>时间浪费，产生大量临时对象，影响 young gc 甚至 full gc</li>
<li><code>javac StringContact.java</code></li>
<li><code>javap -l -c -p .\StringContact.class</code></li>
</ul>
</li>
<li><p>StringBuffer 和 StringBuilder 三个区别</p>
<ul>
<li>线程安全</li>
<li>缓冲区 StringBuffer 使用了缓冲区（toString方法）</li>
<li>性能 StringBuilder 性能远大于 StringBuffer</li>
</ul>
</li>
</ul>
<h4 id="分不清深浅拷贝"><a href="#分不清深浅拷贝" class="headerlink" title="分不清深浅拷贝"></a>分不清深浅拷贝</h4><ul>
<li>浅拷贝，属性是引用类型的情况是同一个引用对象</li>
<li>深拷贝，属性是引用类型的情况是不同引用对象</li>
<li>Cloneable接口<ul>
<li>标记接口，同clone方法是不同的</li>
<li>如果类没有实现 Cloneable接口，调用clone方法会报错</li>
<li>Object 提供的clone方法是浅拷贝</li>
</ul>
</li>
</ul>
<h3 id="线程安全"><a href="#线程安全" class="headerlink" title="线程安全"></a>线程安全</h3><h4 id="用不好-Synchronized-关键字"><a href="#用不好-Synchronized-关键字" class="headerlink" title="用不好 Synchronized 关键字"></a>用不好 Synchronized 关键字</h4><ul>
<li><p>多线程操作变量的过程</p>
</li>
<li><p>synchronized 方法并不会被继承，需要在子类中重写指定</p>
</li>
<li><p>标注在哪里</p>
<ul>
<li>方法声明，非静态方法（对象锁）、静态方法（类对象锁，类锁）</li>
<li>方法体</li>
</ul>
</li>
<li><p>怎么实现的</p>
<ul>
<li>monitor enter 和 monitor exit</li>
</ul>
</li>
<li><p>JDK优化</p>
<ul>
<li>偏向锁</li>
<li>轻量级锁（自旋）</li>
<li>重量级锁</li>
</ul>
</li>
</ul>
<h4 id="多线程下如何更新值"><a href="#多线程下如何更新值" class="headerlink" title="多线程下如何更新值"></a>多线程下如何更新值</h4><ul>
<li>多线程下  i++ 大概率会得到不符合预期的结果<ul>
<li>取数、累加、存储，不是原子性</li>
<li>常用的原子类，AtomicInteger ，CAS操作；悲观锁，互斥同步（同一时刻有且只有一个线程操作数据）；乐观锁，非阻塞同步锁，cas实现，需要解决 <strong>aba</strong> 问题（内部维护modCount只增不减，大多数aba问题不会产生）</li>
</ul>
</li>
</ul>
<h4 id="提到阻塞队列，是不是很懵"><a href="#提到阻塞队列，是不是很懵" class="headerlink" title="提到阻塞队列，是不是很懵"></a>提到阻塞队列，是不是很懵</h4><ul>
<li><p>关于阻塞队列</p>
<ul>
<li><p>核心定义：支持两个附加操作的队列，队列空则等；队列满则等</p>
</li>
<li><p>四种处理方法，生产者和消费者的过程</p>
<table>
<thead>
<tr>
<th>方法</th>
<th>抛出异常</th>
<th>返回特殊值</th>
<th>一直阻塞</th>
<th>超时退出</th>
</tr>
</thead>
<tbody><tr>
<td>插入</td>
<td>add</td>
<td>offer</td>
<td>put</td>
<td>offer(time)</td>
</tr>
<tr>
<td>移除</td>
<td>remove</td>
<td>poll</td>
<td>take</td>
<td>poll(time)</td>
</tr>
<tr>
<td>检查</td>
<td>element</td>
<td>pee</td>
<td>-</td>
<td>-</td>
</tr>
</tbody></table>
</li>
</ul>
</li>
</ul>
<h4 id="并不是什么时候都适合用Copy-On-Write"><a href="#并不是什么时候都适合用Copy-On-Write" class="headerlink" title="并不是什么时候都适合用Copy-On-Write"></a>并不是什么时候都适合用Copy-On-Write</h4><ul>
<li><p>并发对同一个集合进行读取会抛出异常</p>
<ul>
<li>ConcurrentModificationExpcetion</li>
</ul>
</li>
<li><p>使用 CopyOnWrite 容器解决并发读写问题</p>
<ul>
<li>是一种优化策略，是一种延时懒惰策略，是对读写分离（不同的容器）思想的实现</li>
<li>jdk17 add 切换成 synchronized 锁 ；之前是 Reentlock</li>
<li>优点：并发读不需要加锁，提高了程序并发度</li>
<li>缺点：内存占用问题、一致性问题</li>
<li>应用场景：适合读（不加锁）多写少的并发场景，例如：白名单、黑名单</li>
<li>注意：减少扩容开销、使用批量添加</li>
</ul>
</li>
<li><p>对比 Collections.synchronizedList</p>
<ul>
<li>都可以实现线程安全的集合</li>
<li>CopyOnWrite 写操作不仅要枷锁，而且对内部数组进行了 copy 写性能更差</li>
<li>CopyOnWrite 直接读，读性能高</li>
</ul>
</li>
</ul>
<h4 id="用不好-ThreadLocal-极有可能出现内存泄漏"><a href="#用不好-ThreadLocal-极有可能出现内存泄漏" class="headerlink" title="用不好 ThreadLocal 极有可能出现内存泄漏"></a>用不好 ThreadLocal 极有可能出现内存泄漏</h4><ul>
<li>不恰当理解<ul>
<li>用途是解决多线程并发（同步）问题</li>
<li>为了解决多线程访问资源时共享问题</li>
</ul>
</li>
<li>基本原理<ul>
<li>同一个ThreadLocal所包含的对象，在不同的 Thread 中有不同的副本（每个线程需要自己独立的实例且该实例需要在多个方法中使用）</li>
</ul>
</li>
<li>使用误区<ul>
<li>不支持继承，父子线程</li>
<li><strong>遇到线程池，如果不及时清理现场，会造成数据混乱</strong></li>
</ul>
</li>
<li>实现方式<ul>
<li>维护线程与实例的映射 ThreadLocal 维护MAP 需要锁</li>
<li><strong>线程中有MAP维护 ThreadLocal与实例的映射，存在内存泄漏</strong></li>
</ul>
</li>
</ul>
<h3 id="Spring中常见的坑"><a href="#Spring中常见的坑" class="headerlink" title="Spring中常见的坑"></a>Spring中常见的坑</h3><h4 id="默认bean名称造成空指针"><a href="#默认bean名称造成空指针" class="headerlink" title="默认bean名称造成空指针"></a>默认bean名称造成空指针</h4><h4 id="不自动注入还会获取上下文吗"><a href="#不自动注入还会获取上下文吗" class="headerlink" title="不自动注入还会获取上下文吗"></a>不自动注入还会获取上下文吗</h4><ul>
<li><p>Spring 核心时容器，但是容器不是唯一</p>
<ul>
<li>不常用的容器实现 BeanFactory</li>
<li>高级实现，继承 BeanFactory 派生的应用上下文 ApplicationContext</li>
</ul>
</li>
<li><p>获取应用上下文四种方式</p>
<ul>
<li>ApplicationContextInitizer<ul>
<li>Use Initializer</li>
</ul>
</li>
<li>ApplicationListener</li>
</ul>
</li>
<li><p>多线程 Spring Bean 数据不符合预期</p>
</li>
</ul>
<h3 id="SpringBoot常见的坑"><a href="#SpringBoot常见的坑" class="headerlink" title="SpringBoot常见的坑"></a>SpringBoot常见的坑</h3><h4 id="配置数据总是出错？搞清楚加载顺序"><a href="#配置数据总是出错？搞清楚加载顺序" class="headerlink" title="配置数据总是出错？搞清楚加载顺序"></a>配置数据总是出错？搞清楚加载顺序</h4><p><strong>SpringBoot 配置文件</strong></p>
<ul>
<li>SpringBoot 使用一个全局的配置文件，且配置文件名是固定的。配置文件的作用是用来修改  SpringBoot 自动配置的默认值</li>
<li>可以使用 application.properties 格式 也可以用使用 application.yml 格式</li>
<li>由于 YAML 格式紧凑且可读性高，所以，SpringBoot 支持并推荐使用  YAML 格式的配置文件</li>
<li>如果两种配置文件同时存在的时候，默认优先使用 .properties 配置文件</li>
</ul>
<h3 id="Redis中常见的坑"><a href="#Redis中常见的坑" class="headerlink" title="Redis中常见的坑"></a>Redis中常见的坑</h3><h4 id="怎么选择正确数据类型"><a href="#怎么选择正确数据类型" class="headerlink" title="怎么选择正确数据类型"></a>怎么选择正确数据类型</h4><ul>
<li>几乎所有的数据都可以使用 string 表示<ul>
<li>以用户信息数据为例<ul>
<li>UserInfo id 1 name isssac age 19 gender m 键中包含id</li>
</ul>
</li>
</ul>
</li>
<li>String 类型存储数据弊端<ul>
<li>浪费存储空间，key也是需要存储空间</li>
<li>管理、维护会成为噩梦，Redis 中存在大量的 KV 对象</li>
<li>key 冲突的几率变高（不同的业务系统共用一个 Redis 服务）</li>
<li>用map存储 user_1 {id:1, name: issac}</li>
<li>存储json字符串是否可行？<ul>
<li>反序列化操作的效率低下</li>
<li>结合业务场景需求</li>
</ul>
</li>
</ul>
</li>
<li>key 的命名策略（建议）<ul>
<li>同一个 Redis 服务被公司中的各个业务线共用<ul>
<li>业务线名称+工程名+模块名+（有意义的）键名</li>
<li>cbas_recsys_classinfo_item_user_1</li>
</ul>
</li>
</ul>
</li>
<li>常用数据类型及其适用场景<ul>
<li>string 应用最为广泛的数据类型，例如：计数器 session 等键值独立的数据</li>
<li>hash 存储结构化对象，KV共同构成一个对象信息</li>
<li>list 队列、栈、有界队列（控制队列中的个数），</li>
<li>set 去重、无序的数据集合，在类似于社交的业务功能上有广泛应用，例如：共同关注、共同喜好、数据去重</li>
<li>sortedset 带有权重的集合，在类似排行榜业务上有防范应用，且可以实现范围查找</li>
</ul>
</li>
</ul>
<h4 id="使用了事务功能，怎么没回滚"><a href="#使用了事务功能，怎么没回滚" class="headerlink" title="使用了事务功能，怎么没回滚"></a>使用了事务功能，怎么没回滚</h4><ul>
<li><p>Redis事务</p>
<ul>
<li><p>事务基础：四个指令 MULTI EXEC DISCARD WATCH</p>
</li>
<li><p>事务可以一次执行多个命令，并且带有以下两个重要的保证，单独的隔离操作、原子操作</p>
</li>
<li><pre><code class="sh">docker run --restart=always -p 6379:6379 --name myredis -d redis:7.0.12</code></pre>
</li>
<li></li>
</ul>
</li>
</ul>
<h4 id="Redis-性能上不去，可能是有-Big-Key"><a href="#Redis-性能上不去，可能是有-Big-Key" class="headerlink" title="Redis 性能上不去，可能是有 Big Key"></a>Redis 性能上不去，可能是有 Big Key</h4><ul>
<li>数据量大的key，比如字符串 <strong>Value值非常大（大于10KB）</strong>、<strong>哈希、列表、集合、有序集合元素多（元素个数大于 5000）</strong></li>
<li>Big Key 造成的危害<ul>
<li>内存不均、超时阻塞、网络流量阻塞、过期删除、迁移困难</li>
</ul>
</li>
</ul>
<p><strong>怎么产生的（基本上是疏忽、考虑不周全造成）</strong></p>
<ul>
<li>社交类场景：典型的是粉丝列表，对于明显或者大V来说，需要特殊设计，否则，就造成了Big Key</li>
<li>汇总统计类场景：每天都会产生报表数据，报表数据汇总到一个 key，日积月累就成了 BigKey</li>
<li>日常缓存类场景：对DB中的数据进行缓存，大表（存在大字段）很可能会产生 BigKey</li>
</ul>
<p><strong>如何发现 Big Key</strong></p>
<ul>
<li>redis-cli 提供了 –bigkeys 来查找 bigkey ：给出了每种数据结构的 top 1 bigkey</li>
<li>Redis4.0 提供 memory usage 命令可以计算每个键值的字节数（包括键值对和指针一共需要的内存）</li>
</ul>
<p><strong>删除 Big Key 不要贸然行动</strong></p>
<ul>
<li>string 可以直接使用del，不会产生阻塞</li>
<li>dict 使用hscan 命令每次获取部分 field-value ，再使用hdel 删除每个field</li>
<li>list 使用 ltrim 命令渐进式删除列表元素，直到把列表删除</li>
<li>set 使用 sscan 命令，每次获取部分元素，再使用 srem 命令删除每个元素</li>
<li>sortedset 使用 zcan 命令，每次获取部分元素，再使用 zremrangebyrank 命令删除元素</li>
</ul>
<h4 id="Redis-怎么出现内存耗尽"><a href="#Redis-怎么出现内存耗尽" class="headerlink" title="Redis 怎么出现内存耗尽"></a>Redis 怎么出现内存耗尽</h4><ul>
<li>业务不断发展，缓存数据不断增多，需要消耗 Redis 内存<ul>
<li>不可避免</li>
</ul>
</li>
<li>无效的（过期的）数据没有及时清理，需要消耗 Redis 内存</li>
<li>没有对“冷数据”进行降级，需要消耗 Redis 内存</li>
</ul>
<p><strong>使用 EXPIRE 命令将 KEY 标记为 Volatile 易失的</strong></p>
<ul>
<li>使用 EXPIRE key seconds 命令给 key 设置生存时间</li>
<li>如果一个命令只是修改一个带生存时间的 key 的值而不是用一个新 key 的值来代替它的，那么生存时间不会被改变 rename incr 不会变</li>
<li>persist 可以再不删除key的情况下，移除 key 的生存时间，让key重写成为一个持久的key</li>
<li>可以对一个已经有生存时间的 key 执行 EXPIRE 命令，新指定的生存时间会取代旧的生存时间</li>
</ul>
<p><strong>Redis过期删除策略</strong></p>
<ul>
<li>定时删除，对于个每个设置了过期时间的 key 都会创建一个定时器，一旦达到过期时间就立即删除</li>
<li>惰性删除：当访问一个key，才判断是否过期，过期则删除</li>
<li>定期删除：每隔一段时间，扫描Redis中过期的key字典，并清除过期的key</li>
<li>Redis 同时使用了定期删除 + 惰性删除</li>
</ul>
<h4 id="有了过期机制，内存还是不够用"><a href="#有了过期机制，内存还是不够用" class="headerlink" title="有了过期机制，内存还是不够用"></a>有了过期机制，内存还是不够用</h4><p><strong>为什么不够用</strong></p>
<ul>
<li>业务缓存数据需求量大，占用大量的内存空间</li>
<li>过期 key 虽然有很多，但是不能 及时失效</li>
</ul>
<p><strong>Redis内存淘汰策略</strong></p>
<ul>
<li>内存达到 maxmemory 极限时，使用某种算法来决定清理掉哪些数据</li>
<li>常用内存淘汰机制<ul>
<li>noeviction 读请求可以写请求拒绝</li>
<li>allkeys-lru 最近最久没有被使用</li>
<li>allkeys-random 随机</li>
<li>volatile-lru 最早设置了过期时间的key</li>
<li>volatile-random 随机过期时间的key</li>
<li>volatitle-ttl 剩余的ttl时间，越小越优先</li>
</ul>
</li>
</ul>
<h4 id="如何解决频繁的命令往返造成的性能瓶颈"><a href="#如何解决频繁的命令往返造成的性能瓶颈" class="headerlink" title="如何解决频繁的命令往返造成的性能瓶颈"></a>如何解决频繁的命令往返造成的性能瓶颈</h4><ul>
<li>Redis 客户端和服务端的交互模型<ul>
<li>是一个基于 Request 一个 Response 的<strong>同步</strong>请求服务</li>
<li>数据包往返于两端的时间 RTT</li>
</ul>
</li>
<li>Redis pipeline（流水线） 的交互模型<ul>
<li>client &lt;-&gt; client buffer &lt;-&gt;redis server</li>
<li>减少客户端和服务端连接</li>
<li>使用队列实现</li>
</ul>
</li>
<li>pipeline 与原生批量命令对比<ul>
<li>原生批量命令是原子性，pipeline是非原子性</li>
<li>原生命令一次只能执行一种命令，pipeline 支持批量执行不同命令</li>
<li>原生批量命令是服务端实现</li>
</ul>
</li>
<li>注意事项<ul>
<li>命令个数不能太多，数据量过大</li>
<li>会安装指令缓冲的顺序执行，但是可能会穿插其他客户端发送来的命令，即时序性不能保证</li>
<li>某个指令异常，会继续执行</li>
</ul>
</li>
</ul>
<h4 id="你的代码有没有缓存穿透隐患"><a href="#你的代码有没有缓存穿透隐患" class="headerlink" title="你的代码有没有缓存穿透隐患"></a>你的代码有没有缓存穿透隐患</h4><ul>
<li>查询一个一定不存在的数据，如果规则是从数据库中查不到数据则不写入缓存，这会导致这个不存在的数据每次请求都要到数据库中查询</li>
<li>问题1：系统启动初期已经预置了数，但是并未加载到Redis中，导致前期大量的请求由MYSQL 承担</li>
<li>问题2：可以利用不存在的key的频繁攻击应用，流量大时，可能会使数据库宕机</li>
</ul>
<p>如何解决</p>
<ul>
<li>缓存预热：系统上线后，提前将相关的缓存数据直接加载到缓存系统</li>
<li>如果查询数据库为空，直接设置一个默认值（无意义）存放到缓存，这样第二次到缓存中获取就有值了，则不会继续访问数据库<ul>
<li>设置过期时间</li>
<li>更新数据库时及时更新缓存</li>
</ul>
</li>
<li>在数据处理层，<strong>进行数据校验</strong>，判等数据类型和数据范围</li>
<li><strong>使用布隆过滤器</strong>，把所有可能存在的数据哈希到一个足够大的 bitmap中，一个一定不存在的数据会被 bitmap拦截掉</li>
</ul>
<h4 id="出现缓存雪崩"><a href="#出现缓存雪崩" class="headerlink" title="出现缓存雪崩"></a>出现缓存雪崩</h4><ul>
<li>热点数据集中失效</li>
<li>瞬时请求都会被转发到 MYSQL 给后端数据库造成瞬时压力</li>
</ul>
<p>如何解决</p>
<ul>
<li>过期时间错开（可以在一个基础时间上增减一个随机值），避免热点数据集中失效</li>
<li>本地缓存 （JVM Cache） + Hystrix 限流&amp;降级</li>
</ul>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2024/03/07/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BPyTorch/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2024/03/07/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BPyTorch/" class="post-title-link" itemprop="url">一步一步之PyTorch</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2024-03-07 12:25:21" itemprop="dateCreated datePublished" datetime="2024-03-07T12:25:21+08:00">2024-03-07</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2024-04-21 23:22:32" itemprop="dateModified" datetime="2024-04-21T23:22:32+08:00">2024-04-21</time>
              </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>4.9k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="为什么学习PyTorch"><a href="#为什么学习PyTorch" class="headerlink" title="为什么学习PyTorch"></a>为什么学习PyTorch</h2><ul>
<li><p>深度学习框架太多不知道如何选择</p>
</li>
<li><p>开源源码很多，阅读和修改很吃力</p>
</li>
<li><p>解决实际工程任务，思路不清晰，不知道如何入手</p>
</li>
<li><p>项目实战 cnn 卷积 rnn 循环网络 gan</p>
</li>
<li><p><strong>模型保存与部署、调参技巧、优化思想</strong></p>
</li>
</ul>
<p><strong>前置知识</strong></p>
<ul>
<li>机器学习基本概念</li>
<li>Python编程基础</li>
<li>线性代数、概率论</li>
<li>Linux编程</li>
</ul>
<p><strong>学习资料</strong></p>
<ul>
<li><p>机器学习白皮书</p>
</li>
<li><p>线性代数</p>
</li>
<li><p>统计学习方法</p>
</li>
<li><p>深度学习花书</p>
</li>
<li><p>吴恩达视频</p>
</li>
</ul>
<h2 id="初识-PyTorch"><a href="#初识-PyTorch" class="headerlink" title="初识 PyTorch"></a>初识 PyTorch</h2><p>Facebook 2007年开源，Torch -&gt; PyTorch。</p>
<h3 id="PyTorch-VS-TensorFlow"><a href="#PyTorch-VS-TensorFlow" class="headerlink" title="PyTorch VS TensorFlow"></a>PyTorch VS TensorFlow</h3><p>PyTorch</p>
<ul>
<li>简洁性（编程同Python几乎一致）</li>
<li>动态计算</li>
<li>visdom</li>
<li>部署不方便，看成 python后台服务，比如flask</li>
</ul>
<p>TensorFlow 1.0</p>
<ul>
<li>接口复杂</li>
<li>静态图（2.0 Eager Execution 已经引入动态图）</li>
<li>Tensorboard（可视化）</li>
<li>部署方便 TF serving（专门针对Tensorflow 模型调度更好）</li>
</ul>
<h3 id="静态图与动态图"><a href="#静态图与动态图" class="headerlink" title="静态图与动态图"></a>静态图与动态图</h3><p><strong>编程语言的执行本身就是个图的遍历</strong></p>
<p>动态图：编好程序即可执行</p>
<p>静态图：先搭建计算图，后运行；允许编译器进行优化</p>
<h3 id="PyTorch环境搭建"><a href="#PyTorch环境搭建" class="headerlink" title="PyTorch环境搭建"></a>PyTorch环境搭建</h3><p>Ubuntu16.04 、CUDA+cuDNN、Python3+pip3 Anaconda、PyTorch</p>
<ul>
<li><p>为什么选择 Ubuntu</p>
<ul>
<li>安装双系统，不要使用虚拟机</li>
<li>参考安装教程：<a href="https://www.php.cn/linux-373791.html" target="_blank" rel="noopener">https://www.php.cn/linux-373791.html</a></li>
</ul>
</li>
<li><p>CUDA</p>
<ul>
<li>CUDA9.0 10.0 10.1</li>
<li>cuDNN</li>
<li><a href="https://www.imooc.com/article/303675" target="_blank" rel="noopener">https://www.imooc.com/article/303675</a></li>
</ul>
</li>
<li><p>Python3 OR Anaconda</p>
<ul>
<li>Python3 + pip3安装所需的依赖包</li>
<li>Anaconda 安装源（Python全家桶）</li>
</ul>
</li>
<li><p>加速镜像</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 添加清华源的pytorch</span></span><br><span class="line">conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/</span><br><span class="line">conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/</span><br><span class="line">conda config --<span class="built_in">set</span> show_channel_urls yes</span><br><span class="line">conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/</span><br><span class="line"></span><br><span class="line">conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c nvidia  <span class="comment"># 删除安装命令最后的 -c pytorch，才会采用清华源安装。</span></span><br></pre></td></tr></table></figure>



</li>
</ul>
<h2 id="PorTorch-基础"><a href="#PorTorch-基础" class="headerlink" title="PorTorch 基础"></a>PorTorch 基础</h2><h3 id="机器学习基本构成元素"><a href="#机器学习基本构成元素" class="headerlink" title="机器学习基本构成元素"></a>机器学习基本构成元素</h3><ul>
<li>分类与回归问题<ul>
<li>图像分类，离散值，向量 [0.1,0.1,0.1,0.1,0,0,0,5,0.1,0] 10维向量，概率分布，概率值加在一起是1，离散预测是分类问题，</li>
<li>股票价格波动曲线，连续值的预测，股票价格、身高预测</li>
</ul>
</li>
<li>构成元素<ul>
<li>模型，f(x)</li>
<li>样本，挖掘，y = f(x)，包括属性x（样本描述）和标签y</li>
<li>训练，比如 f(x) = wx + b ，求解的过程，深度学习过程中参数比样本多；</li>
<li>推理，学习，计算标签的过程，拿到一堆x</li>
<li>测试，模型性能评估，ROC曲线</li>
</ul>
</li>
</ul>
<h3 id="PorTorch-基本概念"><a href="#PorTorch-基本概念" class="headerlink" title="PorTorch 基本概念"></a>PorTorch 基本概念</h3><ul>
<li>Tensor 张量 <code>h*w*c</code> 任意维度的数据，标量（数字 0阶张量1,2,3）、向量（一维表格 1阶张量 [1,2,13]）、矩阵（二阶张量，二维表格），更加泛化的概念</li>
<li>Variable autograd 变量，表达参数，对于想要求解的模型，未知数</li>
<li>nn.Module 封装解决计算机视觉需要的网路结构</li>
</ul>
<h3 id="Tensor-基本概念"><a href="#Tensor-基本概念" class="headerlink" title="Tensor 基本概念"></a>Tensor 基本概念</h3><ul>
<li><p>任意维度的数据</p>
<p><img src="C:%5CUsers%5Cadmin%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20240413215137646.png" alt="image-20240413215137646"></p>
</li>
<li><p>样本 + 模型</p>
<ul>
<li>Tensor 对样本描述</li>
<li>Y = WX + b，未知数跟变量都是 Tensor</li>
</ul>
</li>
</ul>
<h4 id="类型"><a href="#类型" class="headerlink" title="类型"></a>类型</h4><ul>
<li>torch.float32、torch.float64、torch.float16</li>
</ul>
<h4 id="创建"><a href="#创建" class="headerlink" title="创建"></a>创建</h4><ul>
<li>Tensor(*size) 基础构造函数</li>
<li>Tensor(data) 类似np.array</li>
<li>ones(*size) 全1Tensor</li>
<li>zeros(*size) 全0Tensor</li>
<li>eye(*size) 对角线1，其他为0</li>
<li>arange(s,e,step)，从s到e，步长是step</li>
</ul>
<h4 id="属性"><a href="#属性" class="headerlink" title="属性"></a>属性</h4><ul>
<li>torch.dtype、torch.device（存储的设备cpu还是gpu） 、torch.layout （内存布局的对象）三种属性</li>
<li>torch.tensor([1,2,3],dbtype=torch.float32,device=torch.device(‘cpu’))</li>
<li>稀疏的张量 torch.sparse_coo_tensor coo类型表示了非零元素的坐标形式，稀疏表示了非零元素的个数，矩阵的秩（线性可表示），稀疏是模型变得简单，参数为0的元素可以消掉；减少内存消耗</li>
</ul>
<h4 id="运算"><a href="#运算" class="headerlink" title="运算"></a>运算</h4><ul>
<li>加法运算 add 或者 + ，加 _ 会对a的值修改</li>
<li>哈达玛积（对应元素相乘）mul 或者 * <strong>容易跟矩阵运算搞错</strong></li>
<li>除法 div</li>
<li>矩阵运算<ul>
<li>二维矩阵 torch.mm() torch.matmul()</li>
<li>高维的 Tensor （dim&gt;2）矩阵乘法仅在最后两个维度上，要求前面维度必须保持一致</li>
</ul>
</li>
<li>幂运算<ul>
<li>pow(a,2) 或者 <code>**</code> 下划线 </li>
</ul>
</li>
<li>开方运算<ul>
<li>sqrt()</li>
</ul>
</li>
<li>对数运算<ul>
<li>log2(a)</li>
</ul>
</li>
</ul>
<h4 id="广播机制"><a href="#广播机制" class="headerlink" title="广播机制"></a>广播机制</h4><ul>
<li>in-place 操作</li>
<li>广播机制 张量参数可以自动扩展为相同大小</li>
<li>需要满足两个条件<ul>
<li>每个张量至少有一个维度</li>
<li>满足右对齐</li>
<li>torch.rand(2,1,3) + torch.rand(3)， 补足 torch(1,1,3)</li>
</ul>
</li>
</ul>
<h4 id="取整-取余"><a href="#取整-取余" class="headerlink" title="取整/取余"></a>取整/取余</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line">a = torch.rand(<span class="number">2</span>,<span class="number">2</span>)</span><br><span class="line">a = a * <span class="number">10</span></span><br><span class="line">print(a)</span><br><span class="line">print(torch.floor(a))</span><br><span class="line">print(torch.ceil(a))</span><br><span class="line">print(torch.round(a))</span><br><span class="line">print(torch.trunc(a))</span><br><span class="line">print(torch.frac(a))</span><br><span class="line">print(a % <span class="number">2</span>)</span><br></pre></td></tr></table></figure>

<h4 id="比较eq"><a href="#比较eq" class="headerlink" title="比较eq"></a>比较eq</h4><p>取前K大/前K小/第K小的数值</p>
<p>判断是否为finite（有界）/inf（无界）/nan</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line">a = torch.rand(<span class="number">2</span>,<span class="number">3</span>)</span><br><span class="line">b = torch.rand(<span class="number">2</span>,<span class="number">3</span>)</span><br><span class="line"></span><br><span class="line">print(a)</span><br><span class="line">print(b)</span><br><span class="line"></span><br><span class="line">print(torch.eq(a,b))</span><br><span class="line">print(torch.equal(a,b))</span><br><span class="line">print(torch.ge(a,b))</span><br><span class="line">print(torch.gt(a,b))</span><br><span class="line">print(torch.le(a,b))</span><br><span class="line">print(torch.lt(a,b))</span><br><span class="line">print(torch.ne(a,b))</span><br><span class="line"></span><br><span class="line"><span class="comment"># sort</span></span><br><span class="line">a = torch.tensor([[<span class="number">1</span>,<span class="number">4</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">5</span>],[<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>]])</span><br><span class="line">print(a.shape)</span><br><span class="line">print(torch.sort(a,dim=<span class="number">0</span>,descending=<span class="literal">True</span>))</span><br><span class="line"><span class="comment"># topk</span></span><br><span class="line">a = torch.tensor([[<span class="number">2</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="number">5</span>],[<span class="number">2</span>,<span class="number">3</span>,<span class="number">5</span>,<span class="number">1</span>,<span class="number">4</span>]])</span><br><span class="line">print(a.shape)</span><br><span class="line"></span><br><span class="line">print(torch.topk(a,k=<span class="number">2</span>,dim=<span class="number">0</span>))</span><br><span class="line"></span><br><span class="line">a = torch.rand(<span class="number">2</span>,<span class="number">3</span>)</span><br><span class="line">print(a)</span><br><span class="line">print(torch.isfinite(a))</span><br><span class="line">print(torch.isfinite(a/<span class="number">0</span>))</span><br><span class="line">print(torch.isinf(a/<span class="number">0</span>))</span><br><span class="line">print(torch.isnan(a))</span><br></pre></td></tr></table></figure>

<h4 id="三角函数"><a href="#三角函数" class="headerlink" title="三角函数"></a><strong>三角函数</strong></h4><p>相似度用cos函数比较，越小相似度越高</p>
<p>预测和角度有关系的</p>
<h4 id="其他数学函数"><a href="#其他数学函数" class="headerlink" title="其他数学函数"></a><strong>其他数学函数</strong></h4><ul>
<li>abs （绝对值，没办法求导，l1 loss）、sigmoid（激活函数，越小趋近于0，越大趋近于1，外观上同符号函数相似，是符号函数连续）、sign（符号函数，分段函数，机器学习中提到的分类问题，对输出结果数据离散化，不是连续函数，不能求导优化）</li>
</ul>
<h4 id="统计学相关的函数"><a href="#统计学相关的函数" class="headerlink" title="统计学相关的函数"></a><strong>统计学相关的函数</strong></h4><ul>
<li>mean 平均值、sum 返回总和、prod 所有元素的积、max 最大值、min 最小值、argmax 最大值索引、argmin 最小值索引</li>
<li>std 返回标准差、var 方差、median 中间值、mode 众数值、histc 直方图（表达数据统计的，对旋转不敏感，不鲁棒）、bincount 每个值的频数</li>
</ul>
<h4 id="分布函数"><a href="#分布函数" class="headerlink" title="分布函数"></a>分布函数</h4><ul>
<li>distributions 包含可参数化的概率分布和采样函数<ul>
<li>得分函数<ul>
<li>强化学习中策略梯度方法的基础</li>
</ul>
</li>
<li>pathwise derivative 估计器<ul>
<li>变分自动编码器中的重新参数化技巧</li>
</ul>
</li>
</ul>
</li>
<li>Bernoulli 、Beta 、Binomial 、OneHotCategorical、TransformedDistribution 等等分布函数</li>
<li>KL Divergence 度量两种分布的差异</li>
<li>Transforms 两种分布之间的转换</li>
<li>Constraint 分布的约束</li>
</ul>
<h4 id="随机抽样"><a href="#随机抽样" class="headerlink" title="随机抽样"></a>随机抽样</h4><ul>
<li>定义随机种子<ul>
<li>torch.manual_seed(seed)</li>
</ul>
</li>
<li>定义随机数满足的分布<ul>
<li>torch.normal()</li>
</ul>
</li>
</ul>
<h4 id="范数运算"><a href="#范数运算" class="headerlink" title="范数运算"></a>范数运算</h4><ul>
<li>范数<ul>
<li>在泛函分析中，它定义在赋范线性空间中，并满足一定的条件，即1非负性；2齐次性；3三角不等式</li>
<li>常被用来度量某个向量空间（或矩阵）中每个向量的<strong>长度或大小</strong></li>
</ul>
</li>
<li>0范数/1范数（绝对值和）/2范数（平方和）/p范数/核范数<ul>
<li>torch.dist(input,other,p =2) 计算p范数</li>
<li>torch.norm() 计算2范数</li>
</ul>
</li>
</ul>
<h4 id="矩阵分解"><a href="#矩阵分解" class="headerlink" title="矩阵分解"></a>矩阵分解</h4><p><strong>常见的矩阵分解</strong></p>
<ul>
<li>LU分解：将矩阵A分解成L（下三角）矩阵和U（上三角）矩阵的乘积</li>
<li>QR分解：将原矩阵分解成一个正交矩阵Q和一个上三角矩阵R的乘积</li>
<li>EVD分解：特征值分解<ul>
<li>矩阵方阵且满秩（可对角化）</li>
<li>矩阵分解不等于特征降维度</li>
<li>协方差矩阵描述方法和相关性</li>
</ul>
</li>
<li>SVD分解：奇异值分解<ul>
<li>torch.svd()</li>
</ul>
</li>
<li>特征值分解<ul>
<li>矩阵分解为由其特征值和特征向量表示的矩阵之积的方法</li>
<li>特征值 VS 特征向量</li>
</ul>
</li>
</ul>
<h4 id="裁剪运算"><a href="#裁剪运算" class="headerlink" title="裁剪运算"></a>裁剪运算</h4><ul>
<li>对 Tensor 的元素进行范围内过滤<ul>
<li>稳定，正则化，防止过拟合，</li>
<li>loss </li>
</ul>
</li>
<li>常用于梯度裁剪（gradient clipping），即在发生梯度离散或者梯度爆炸时对梯度的处理（x的n次方， x&gt;1 n-&gt;∞ f(x)-&gt;∞ ，x&lt;1，n-&gt;∞，f(x) -&gt;0）</li>
</ul>
<h4 id="索引和数据筛选"><a href="#索引和数据筛选" class="headerlink" title="索引和数据筛选"></a>索引和数据筛选</h4><ul>
<li><p>torch.where(condition,x,y)：按照条件从x和y中选出满足条件元素组成新的tensor</p>
</li>
<li><p>torch.gather(input,dim,index,out=None) 指定维度上按照索引赋值输出tensor</p>
</li>
<li><p>torch.index_select 按照指定索引输出tensor</p>
</li>
<li><p>torch.masked_select 按照 mask输出tensor，输出为向量</p>
</li>
<li><p>torch.take</p>
</li>
<li><p>操作，切片、索引、变形</p>
</li>
<li><p>numpy（可以定义任意维度数据）的相互转换</p>
</li>
</ul>
<h3 id="神经网络基本概念"><a href="#神经网络基本概念" class="headerlink" title="神经网络基本概念"></a>神经网络基本概念</h3><ul>
<li>人工智能领域 -&gt; 机器学习 -&gt; 神经网络 <strong>深度学习</strong>（更多层）</li>
<li>神经网络如下图所示：输入层（神经元）、输出层、隐藏层、<strong>多层感知器</strong></li>
</ul>
<h4 id="感知器基本概念"><a href="#感知器基本概念" class="headerlink" title="感知器基本概念"></a>感知器基本概念</h4><ul>
<li>神经元、感知器、阶跃函数（分类）、激活函数</li>
</ul>
<p>神经网络 VS 深度学习</p>
<ul>
<li>多层感知器 -&gt; 神经网络</li>
<li>多隐层的多层感知器-&gt;深度学习<ul>
<li>CNN</li>
<li>RNN</li>
</ul>
</li>
</ul>
<h4 id="前向运算"><a href="#前向运算" class="headerlink" title="前向运算"></a>前向运算</h4><ul>
<li>计算输出值的过程 <strong>前向传播</strong>，推理 参数已知</li>
</ul>
<h4 id="反向传播"><a href="#反向传播" class="headerlink" title="反向传播"></a>反向传播</h4><ul>
<li>神经网络训练方法</li>
<li>反向传播方法，通过计算输出层与真实值之间的偏差来进行逐层调节参数<ul>
<li>参数更新多少？ 导数和学习率，真实值和预测值的偏差成为损失</li>
</ul>
</li>
</ul>
<h4 id="分类和回归"><a href="#分类和回归" class="headerlink" title="分类和回归"></a>分类和回归</h4><h4 id="过拟合和欠拟合"><a href="#过拟合和欠拟合" class="headerlink" title="过拟合和欠拟合"></a>过拟合和欠拟合</h4><ul>
<li>过拟合，给定训练集的样本表现好，但是在测试集效果差</li>
<li>欠拟合（高偏差），模型拟合不够，在训练集上表现效果差，没有充分的利用数据，预测的准确度低</li>
<li>偏差（Bias） 反应的是模型在样本上的输出与真实值之间误差，即模型本身的精确度</li>
<li>方差（Variance）反应的时模型的每一次输出结果与模型输出期望之间的误差，即模型的稳定性</li>
</ul>
<p><strong>如何防止</strong></p>
<ul>
<li>防止过拟合<ul>
<li><strong>补充数据集（数据增强）</strong></li>
<li><strong>减少模型参数</strong></li>
<li>Dropout</li>
<li>Earlystopping 早停</li>
<li>正则化&amp;稀疏化</li>
</ul>
</li>
<li>防止欠拟合<ul>
<li><strong>加大模型参数</strong></li>
<li>减少正则化参数</li>
<li><strong>更充分的训练</strong></li>
</ul>
</li>
</ul>
<h4 id="正则化问题"><a href="#正则化问题" class="headerlink" title="正则化问题"></a>正则化问题</h4><ul>
<li>L0，L1，L2 无穷范数、核范数<ul>
<li>Pytorch 通过 weight_decay 实现</li>
</ul>
</li>
<li>Dropout<ul>
<li>nn.Dropout(p=0.5)</li>
</ul>
</li>
</ul>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2024/02/26/%E4%BC%9A%E8%AE%AE%E7%BA%AA%E8%A6%81/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2024/02/26/%E4%BC%9A%E8%AE%AE%E7%BA%AA%E8%A6%81/" class="post-title-link" itemprop="url">会议纪要</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2024-02-26 20:24:46" itemprop="dateCreated datePublished" datetime="2024-02-26T20:24:46+08:00">2024-02-26</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2024-03-05 12:25:20" itemprop="dateModified" datetime="2024-03-05T12:25:20+08:00">2024-03-05</time>
              </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>118</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><ul>
<li>新功能无法推送</li>
<li>没法特定人群推送</li>
<li>特定时间点没法推送</li>
<li>特定渠道内容定制</li>
</ul>
<h2 id="问题-1"><a href="#问题-1" class="headerlink" title="问题+"></a>问题+</h2><p>矛盾点</p>
<ul>
<li>推荐和运营策略的矛盾，通过参数权重</li>
<li>运营策略和策略的矛盾，通过时间和空间区分</li>
</ul>
<h2 id="2024-03-01"><a href="#2024-03-01" class="headerlink" title="2024/03/01"></a>2024/03/01</h2><ul>
<li>广告引擎还依赖老物品中心</li>
<li>问财适配服务个股亮点</li>
<li>推荐流量录制、回放</li>
</ul>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2024/02/26/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8B%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2024/02/26/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8B%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/" class="post-title-link" itemprop="url">一步一步之数据分析</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2024-02-26 12:35:27" itemprop="dateCreated datePublished" datetime="2024-02-26T12:35:27+08:00">2024-02-26</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2024-03-27 11:43:16" itemprop="dateModified" datetime="2024-03-27T11:43:16+08:00">2024-03-27</time>
              </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>981</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="互联网数据分析"><a href="#互联网数据分析" class="headerlink" title="互联网数据分析"></a>互联网数据分析</h2><p>数据分析，对数据总结分析出规律进行决策。</p>
<h3 id="数据"><a href="#数据" class="headerlink" title="数据"></a>数据</h3><p><strong>对于事物的描述和记录</strong></p>
<p><strong>数据的特性</strong></p>
<p>根据计量层次，对数据进行分类</p>
<h4 id="定性和定量数据"><a href="#定性和定量数据" class="headerlink" title="定性和定量数据"></a>定性和定量数据</h4><p><strong>定类数据</strong></p>
<p>颜色：白色、红色、黄色</p>
<p><strong>定序数据</strong></p>
<p>受教育层度：小学、初中、高中、大学、硕士、博士</p>
<p><strong>定距数据</strong></p>
<p>温度：20、50、100</p>
<p><strong>定比数据</strong>，可以做数学运算</p>
<p>利润：10万、20万、30万</p>
<h4 id="统计指标"><a href="#统计指标" class="headerlink" title="统计指标"></a>统计指标</h4><p><strong>总量指标</strong></p>
<ul>
<li>GDP，累加和</li>
</ul>
<p><strong>平均指标</strong></p>
<ul>
<li>集中趋势的指标</li>
</ul>
<p><strong>相对指标</strong></p>
<p>比例（各数据/总比）、比率（数据项vs数据项）、倍数</p>
<p>环比（(本期-上期)/上期<code>*</code>100%，注重短期涨幅表现）、同比（(本期-同期)/同期<code>*</code>100%，注重长期涨幅表现）</p>
<ul>
<li>两个有联系的现象数值比例</li>
</ul>
<h4 id="集中趋势指标"><a href="#集中趋势指标" class="headerlink" title="集中趋势指标"></a>集中趋势指标</h4><p>平均值，所有数据组加 / 数据个数，具有一定的误导性，对异常数据不敏感。</p>
<p>中位值，顺序排列后，属于中间位置的数据。</p>
<p>众数，出现次数最多的数值，最密集最频繁。</p>
<ul>
<li>哪个产品最受欢迎？</li>
<li>什么岗位薪酬水平最高？</li>
</ul>
<h3 id="Excel"><a href="#Excel" class="headerlink" title="Excel"></a>Excel</h3><p>基本功能</p>
<ul>
<li>开始<ul>
<li>调整文本样式，字体大小</li>
</ul>
</li>
<li>插入</li>
<li>页面布局</li>
<li>公式栏</li>
<li>数据栏<ul>
<li>引用数据、数据预处理</li>
</ul>
</li>
<li>审阅<ul>
<li>多人协作的</li>
</ul>
</li>
<li>视图<ul>
<li>便于阅读习惯；比如数据量很大，冻结首行</li>
</ul>
</li>
</ul>
<h4 id="常用功能"><a href="#常用功能" class="headerlink" title="常用功能"></a>常用功能</h4><h2 id="Python-数据分析"><a href="#Python-数据分析" class="headerlink" title="Python 数据分析"></a>Python 数据分析</h2><p>python + 开源库 （版本报错 anaconda）</p>
<p><strong>ANACONDA</strong></p>
<ul>
<li>图形化界面</li>
<li>操作简单</li>
<li>可创建多个环境</li>
<li>开源免费</li>
</ul>
<h3 id="开发环境搭建"><a href="#开发环境搭建" class="headerlink" title="开发环境搭建"></a>开发环境搭建</h3><ul>
<li>PyCharm </li>
</ul>
<h3 id="基础语法"><a href="#基础语法" class="headerlink" title="基础语法"></a>基础语法</h3><p><strong>数据类型</strong></p>
<ul>
<li>数值，整数型</li>
<li>字符串</li>
<li>逻辑值 True False</li>
</ul>
<p><strong>数据容器</strong></p>
<p>多种数据类型组成，可以统一操作</p>
<ul>
<li>列表 list</li>
<li>集合 set</li>
<li>字典dic</li>
</ul>
<p><strong>控制流</strong></p>
<h3 id="网络爬虫"><a href="#网络爬虫" class="headerlink" title="网络爬虫"></a>网络爬虫</h3><ul>
<li>定位目标网址</li>
<li>获取网页信息<ul>
<li>Request库</li>
</ul>
</li>
<li>提取目标信息<ul>
<li>网页结构 BeatifulSoop库</li>
</ul>
</li>
</ul>
<h4 id="Requests库"><a href="#Requests库" class="headerlink" title="Requests库"></a>Requests库</h4><p>官方文档，实例代码</p>
<h4 id="BeautifulSoup"><a href="#BeautifulSoup" class="headerlink" title="BeautifulSoup"></a>BeautifulSoup</h4><p>官方文档</p>
<h4 id="阶段目标"><a href="#阶段目标" class="headerlink" title="阶段目标"></a>阶段目标</h4><ul>
<li>电影总量</li>
<li>评分情况</li>
<li>国家分布</li>
</ul>
<h4 id="实现连续抓取"><a href="#实现连续抓取" class="headerlink" title="实现连续抓取"></a>实现连续抓取</h4><ul>
<li>访问链接</li>
<li>获取基础数据</li>
<li>提取数据</li>
<li>页面跳转</li>
</ul>
<h4 id="网页抓取vsAPI接口"><a href="#网页抓取vsAPI接口" class="headerlink" title="网页抓取vsAPI接口"></a>网页抓取vsAPI接口</h4><ul>
<li>网页抓取：网页解析、定位数据、获取数据</li>
<li>API接口：列表、字典数据</li>
</ul>
<h3 id="Pandas库"><a href="#Pandas库" class="headerlink" title="Pandas库"></a>Pandas库</h3><p>处理和分析数据的功能库</p>
<p><strong>Pandas</strong> 是的核心数据分析支持库，提供了快速、灵活、明确的数据结构，旨在简单、直观地处理关系型、标记型数据</p>
<h4 id="什么是DataFrame"><a href="#什么是DataFrame" class="headerlink" title="什么是DataFrame"></a>什么是DataFrame</h4><p>二维数组的形式，类似excel，通过行列定位数据。列数据称为 Series 一维数组</p>
<ul>
<li><code>.loc</code> 和 <code>.iloc</code> 按值、索引选取行</li>
<li>df[列表] 按字段名选取列</li>
<li>df[选取条件] 模糊、精准查询</li>
</ul>
<h4 id="案例"><a href="#案例" class="headerlink" title="案例"></a>案例</h4><p>数据分析步骤</p>
<p><strong>目标确定-数据获取-数据预处理（Pandas）-描述分析（Maplab）-洞察结论-撰写报告</strong></p>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2024/02/05/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BJDK-SpringBooot3%E6%96%B0%E7%89%B9%E6%80%A7/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2024/02/05/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8BJDK-SpringBooot3%E6%96%B0%E7%89%B9%E6%80%A7/" class="post-title-link" itemprop="url">一步一步之JDK&SpringBooot3新特性</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2024-02-05 17:05:32" itemprop="dateCreated datePublished" datetime="2024-02-05T17:05:32+08:00">2024-02-05</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2024-03-07 21:13:45" itemprop="dateModified" datetime="2024-03-07T21:13:45+08:00">2024-03-07</time>
              </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>1.4k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="JDK新特性"><a href="#JDK新特性" class="headerlink" title="JDK新特性"></a>JDK新特性</h2><h3 id="JDK9"><a href="#JDK9" class="headerlink" title="JDK9"></a>JDK9</h3><p>module 可以定义包是否暴露给外部，模块-包-接口、类</p>
<p>步骤</p>
<ol>
<li><p>新建module模块，新建 module-info.java 文件，包括调用模块和被调用模块</p>
</li>
<li><p>被调用模块 module-info.java</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">module</span> testa &#123;</span><br><span class="line">    <span class="keyword">exports</span> com.testa.test1;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>调用模块 module-info.java</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">module</span> testb &#123;</span><br><span class="line">    <span class="keyword">requires</span> testa;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ol>
<h3 id="JDK10"><a href="#JDK10" class="headerlink" title="JDK10"></a>JDK10</h3><p>var 局部变量推导</p>
<ul>
<li>必须能推导实际类型</li>
<li>只用于定义变量</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> test1 = <span class="keyword">new</span> Test1();</span><br><span class="line"><span class="comment">// 必须有初始化</span></span><br><span class="line"><span class="keyword">var</span> test11; <span class="comment">// 报错</span></span><br><span class="line">vat test111 = <span class="keyword">null</span>; <span class="comment">// 报错</span></span><br></pre></td></tr></table></figure>

<p><strong>看不出有什么好处</strong></p>
<h3 id="JDK11"><a href="#JDK11" class="headerlink" title="JDK11"></a>JDK11</h3><ul>
<li><p>java 命令可以直接运行java文件，像其他语言 java hello.java，对于初学者友好些。</p>
</li>
<li><p><code>#!</code> 符号叫做shebang，音译成 “释棒”，解释伴随行，类似shell脚本的<code>#!/bin/bash</code>（以此开头的文件，执行时会调用 /bin/bash 程序执行），可以命令行执行 ./TestC，执行java文件</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">#!/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/bin/java --source 17</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestC</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"Hello World"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ul>
<h3 id="JDK14"><a href="#JDK14" class="headerlink" title="JDK14"></a>JDK14</h3><ul>
<li><p>文本块，多行字符串，三个字符串</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">String test = <span class="string">""</span><span class="string">"</span></span><br><span class="line"><span class="string">    Hello</span></span><br><span class="line"><span class="string">                World</span></span><br><span class="line"><span class="string">                "</span><span class="string">""</span>;</span><br><span class="line">    System.out.println(test);</span><br></pre></td></tr></table></figure>
</li>
<li><p>instanceof 增强</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Object a = <span class="string">"test"</span>;</span><br><span class="line"><span class="keyword">if</span>(a <span class="keyword">instanceof</span> String b) &#123;</span><br><span class="line">    System.out.println(b);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ul>
<h3 id="JDK16"><a href="#JDK16" class="headerlink" title="JDK16"></a>JDK16</h3><ul>
<li><p>Record类型</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 只能初始化1次，属性相当于final</span></span><br><span class="line">TestRecord testRecord = <span class="keyword">new</span> TestRecord(<span class="string">"issac"</span>, <span class="string">"young"</span>);</span><br><span class="line">String name = testRecord.name();</span><br></pre></td></tr></table></figure>

</li>
</ul>
<h3 id="JDK17"><a href="#JDK17" class="headerlink" title="JDK17"></a>JDK17</h3><ul>
<li>Sealed类，类的继承很难管理，使用 Sealed显示管理；父类是 Sealed 类，至少有个继承</li>
<li>Switch 增强，配合instanceOf 增强</li>
</ul>
<h2 id="SpringBoot3"><a href="#SpringBoot3" class="headerlink" title="SpringBoot3"></a>SpringBoot3</h2><h3 id="AOT"><a href="#AOT" class="headerlink" title="AOT"></a>AOT</h3><p>预编译，无法跨平台</p>
<ul>
<li>优点，启动和运行速度快，几十倍的提升，运行直接跟机器操作系统（无jvm）；打包体积小，直接exe；可以用于云服务器，快速启动，朝着云原生方向</li>
<li>缺点，编译后不支持跨平台，比如exe程序不能在linux上运行，springboot直接编译成jar，windows和linux都支持部署；还不支持aop，提前编译好；谨慎使用</li>
</ul>
<h3 id="JIT"><a href="#JIT" class="headerlink" title="JIT"></a>JIT</h3><p>实时编译，程序运行时编译，运行机器码，跨平台基础</p>
<ul>
<li>热点应用，重启之后，出现业务超时，几分钟之后恢复正常</li>
<li>不是每个类都会jit编译，根据类调用的频繁程度</li>
</ul>
<h4 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h4><ul>
<li>预热：初始让程序自动运行热点代码几百次</li>
<li>流量控制：启动时小流量，运行几分钟后再放到正常流量</li>
</ul>
<h3 id="GraalVM"><a href="#GraalVM" class="headerlink" title="GraalVM"></a>GraalVM</h3><p>代替jvm</p>
<ul>
<li><p>下载 <a href="https://www.graalvm.org/" target="_blank" rel="noopener">https://www.graalvm.org/</a> </p>
</li>
<li><p>配置环境变量 <code>$JAVA_HOME</code> 为graalvm的Home目录</p>
</li>
<li><p>在线安装 native-image</p>
</li>
</ul>
<h3 id="新建springboot"><a href="#新建springboot" class="headerlink" title="新建springboot"></a>新建springboot</h3><p>版本号3.0.0</p>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2024/02/04/%E9%9D%A2%E5%90%91%E7%BB%A9%E6%95%88%E7%BC%96%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2024/02/04/%E9%9D%A2%E5%90%91%E7%BB%A9%E6%95%88%E7%BC%96%E7%A8%8B/" class="post-title-link" itemprop="url">面向绩效编程</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2024-02-04 21:42:52" itemprop="dateCreated datePublished" datetime="2024-02-04T21:42:52+08:00">2024-02-04</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2024-02-24 23:00:10" itemprop="dateModified" datetime="2024-02-24T23:00:10+08:00">2024-02-24</time>
              </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>2.7k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="面向绩效编程"><a href="#面向绩效编程" class="headerlink" title="面向绩效编程"></a>面向绩效编程</h2><blockquote>
<p>简历驱动开发，人力资源管理，RDD（Resume Driven Development）</p>
</blockquote>
<p>Red Hat，It’s easy to say “hire good people” but hiring good people is hard.</p>
<h3 id="绩效-Performance"><a href="#绩效-Performance" class="headerlink" title="绩效 Performance"></a>绩效 Performance</h3><p>最早源于英国文官的考核方式。</p>
<h4 id="绩效的意义"><a href="#绩效的意义" class="headerlink" title="绩效的意义"></a>绩效的意义</h4><ul>
<li>企业发展</li>
<li>员工管理</li>
</ul>
<h4 id="成功案例"><a href="#成功案例" class="headerlink" title="成功案例"></a>成功案例</h4><ul>
<li>近因效应 Recency Effect ，对近期发生的事情，印象深刻；远期的事情，印象模糊</li>
<li>做好汇报、写好绩效总结；在绩效考核前期迅猛发力，针对一个领导使用一次</li>
<li>主管亲信，<strong>晕轮效应</strong>，光圈效应，只看重被评估者的某一特质</li>
</ul>
<h3 id="金钱困境"><a href="#金钱困境" class="headerlink" title="金钱困境"></a>金钱困境</h3><h3 id="贫穷的本质"><a href="#贫穷的本质" class="headerlink" title="贫穷的本质"></a>贫穷的本质</h3><p>同名书</p>
<ul>
<li><p>远期规划的丧失</p>
<ul>
<li>教育</li>
<li>温饱</li>
<li>压力</li>
</ul>
</li>
<li><p>贷款</p>
<ul>
<li>生子</li>
<li>婚姻，处理风险的方式</li>
<li>高利贷</li>
</ul>
</li>
<li><p>偏见</p>
</li>
</ul>
<h3 id="薪资瓶颈"><a href="#薪资瓶颈" class="headerlink" title="薪资瓶颈"></a>薪资瓶颈</h3><p>原因是绩效不突出</p>
<p>改善措施</p>
<ul>
<li>自驱力，在公司表现太佛系，丧失要的欲望</li>
<li>主动承担</li>
<li>跳槽</li>
</ul>
<h3 id="谈薪资本"><a href="#谈薪资本" class="headerlink" title="谈薪资本"></a>谈薪资本</h3><ul>
<li>你势在必得的谈判能力，麦肯锡谈判技巧<ul>
<li>换位思考，告诉领导自己下一个阶段的工作计划</li>
</ul>
</li>
<li>你不可替代的工作能力<ul>
<li>挖掘、打磨自己，不仅要自己觉得不一样，还需要同同事比较，比如文档能力</li>
</ul>
</li>
<li>你对金钱如饥似渴的程度，房贷压力重</li>
</ul>
<h2 id="跳出绩效应试的泥潭"><a href="#跳出绩效应试的泥潭" class="headerlink" title="跳出绩效应试的泥潭"></a>跳出绩效应试的泥潭</h2><p>我们知道绩效后，想知道其他人的绩效，比较；绩效不好的情况下。</p>
<p><strong>考试和绩效</strong></p>
<ul>
<li>考试是帮你自己拿到好成绩</li>
<li>职场是帮你领导拿到好成绩，目标和领导的目标对齐</li>
</ul>
<p><strong>渡人就是渡己</strong></p>
<h3 id="职场格局"><a href="#职场格局" class="headerlink" title="职场格局"></a>职场格局</h3><ul>
<li>考试只有对与错</li>
<li>职场却还有格局，<strong>打开格局看结果</strong></li>
</ul>
<h3 id="从单一考虑自己绩效走出来"><a href="#从单一考虑自己绩效走出来" class="headerlink" title="从单一考虑自己绩效走出来"></a>从单一考虑自己绩效走出来</h3><p>“固步自封”的自我绩效考核，沉溺于自己情绪的泥潭</p>
<ul>
<li>我为什么没拿到好绩效</li>
<li>是不是我不够优秀</li>
<li>是不是我产出太少</li>
</ul>
<p><strong>走出你自己的世界</strong></p>
<p>直接问领导，领导会说大环境不好、或者是你这阶段时间表现不够。实际上，领导可能一开始就定好绩效，是一种长期规划，比如需要留住人。</p>
<h3 id="绩效目的"><a href="#绩效目的" class="headerlink" title="绩效目的"></a>绩效目的</h3><ul>
<li>给出评价标准</li>
<li>更客观地评估员工</li>
<li>促进员工进步</li>
</ul>
<h3 id="如何发散自己的思维"><a href="#如何发散自己的思维" class="headerlink" title="如何发散自己的思维"></a>如何发散自己的思维</h3><p>推荐书《思考，快与慢》心理学家获得诺贝尔经济学奖</p>
<ul>
<li>系统1：快系统（自动驾驶）</li>
<li>系统2：慢系统（正常走路，被打断做数学题，深度思考），更多分析问题</li>
</ul>
<p><strong>什么是发散思维</strong></p>
<p>产生一题多解，</p>
<ul>
<li>多用系统2来思考，更多体力放在思考？</li>
<li>以多维度分析问题</li>
<li>保持好奇心</li>
</ul>
<p><strong>如何锻炼发散思维</strong></p>
<ul>
<li>头脑风暴</li>
<li>结构化思维，思维导图</li>
</ul>
<h3 id="一味埋头苦干的影响"><a href="#一味埋头苦干的影响" class="headerlink" title="一味埋头苦干的影响"></a>一味埋头苦干的影响</h3><p><strong>职场两型人</strong></p>
<ul>
<li>埋头苦干家，实干派</li>
<li>油嘴马屁精，擅长沟通交际</li>
</ul>
<p>你是哪类人？</p>
<ul>
<li>能说能做，一说就能说到点子上</li>
<li>善于言谈</li>
<li>善于做事，没有做好向上管理，实时沟通，正确时间说正确的话</li>
</ul>
<h3 id="为了加班而加班"><a href="#为了加班而加班" class="headerlink" title="为了加班而加班"></a>为了加班而加班</h3><p>加班多必须搭配产出多</p>
<p><strong>什么是真加班</strong></p>
<ul>
<li>我要上晚自习，学习新技能，推荐</li>
<li>我承诺的工作做不完，容易疲惫，效率低下，消极</li>
<li>我不想回家，逃避家庭责任</li>
</ul>
<p><strong>什么是假加班</strong></p>
<ul>
<li>别人加班你也加</li>
<li>领导不下班你就不下班</li>
</ul>
<h3 id="小明的加班"><a href="#小明的加班" class="headerlink" title="小明的加班"></a>小明的加班</h3><ul>
<li><p>每天加班到9点</p>
</li>
<li><p>最后一个离开公司</p>
</li>
<li><p>长时间饱和的状态，做事情仔细，力求扩展自己的知识面（工作中）</p>
</li>
</ul>
<p>丧失了思考的时间，无长远规划；</p>
<p>对于自己努力太过自信。</p>
<h3 id="加班的意义"><a href="#加班的意义" class="headerlink" title="加班的意义"></a>加班的意义</h3><ul>
<li>代表工作态度</li>
<li>代表工作效率</li>
</ul>
<h2 id="勇攀高峰"><a href="#勇攀高峰" class="headerlink" title="勇攀高峰"></a>勇攀高峰</h2><h3 id="了解公司的绩效体系"><a href="#了解公司的绩效体系" class="headerlink" title="了解公司的绩效体系"></a>了解公司的绩效体系</h3><p>根据岗位分类、层级</p>
<p><strong>岗位分类</strong></p>
<ul>
<li>管理类<ul>
<li>规划能力，分治算法，分而治之</li>
</ul>
</li>
<li>研发类<ul>
<li>技术能力（发展快的公司不关注，需要研发有产品经理能力）</li>
<li>创新能力</li>
</ul>
</li>
<li>其他，指标</li>
</ul>
<p><strong>能力分类</strong></p>
<ul>
<li>技术能力</li>
<li>业务能力，技术同学跟产品经理</li>
<li>协作能力</li>
</ul>
<p><strong>参与者分类</strong></p>
<ul>
<li>直接主管，直接合作关系</li>
<li>hr，裁判角色，资源平衡</li>
</ul>
<h3 id="收买老员工拯救自己"><a href="#收买老员工拯救自己" class="headerlink" title="收买老员工拯救自己"></a>收买老员工拯救自己</h3><p><strong>老员工不爱带新人</strong></p>
<ul>
<li>不愿传授自己的秘笈</li>
<li>得不到带人的回报</li>
<li>工作面临不断被打断</li>
</ul>
<p><strong>借助他人的力量</strong></p>
<ul>
<li>给予老员工尊重《如何让你喜欢的人喜欢你》</li>
<li>请老员工吃顿饭</li>
<li>主动夸赞老员工，多找亮点</li>
</ul>
<h3 id="改善绩效必杀技"><a href="#改善绩效必杀技" class="headerlink" title="改善绩效必杀技"></a>改善绩效必杀技</h3><p><strong>两种手段</strong></p>
<ul>
<li>心理手段，发生绩效考核前，近因效应（短期），晕轮效应（长期），对比效应（评估者对比）</li>
<li>行为手段，创新思维，汇报艺术，主动送功</li>
</ul>
<h3 id="代码重构"><a href="#代码重构" class="headerlink" title="代码重构"></a>代码重构</h3><p>编程架构</p>
<p><strong>重构前，火眼金睛</strong></p>
<ul>
<li>看清绩效结构</li>
<li>看清领导态度</li>
<li>看清公司环境</li>
</ul>
<p><strong>重构时，能进能退</strong></p>
<ul>
<li>保证质量</li>
<li>保证资源</li>
<li>保证创新，有所沉淀</li>
</ul>
<p><strong>重构后，善于发光</strong></p>
<ul>
<li>与数据挂钩</li>
<li>与质量挂钩</li>
<li>与资源挂钩</li>
</ul>
<h3 id="汇报方式的问题"><a href="#汇报方式的问题" class="headerlink" title="汇报方式的问题"></a>汇报方式的问题</h3><p>决定发展上限，不懂汇报是你的职场绊脚石</p>
<p><strong>汇报技能</strong></p>
<ul>
<li>演讲技能，即时演讲</li>
<li>结构化思维，工作方式，黄金圈法则 Why-How-What</li>
<li>数据分析能力</li>
</ul>
<p><strong>分析汇报能力</strong></p>
<ul>
<li>录音回放</li>
<li>问询他人</li>
</ul>
<h2 id="道歉降低负面效应"><a href="#道歉降低负面效应" class="headerlink" title="道歉降低负面效应"></a>道歉降低负面效应</h2><h3 id="错误的道歉"><a href="#错误的道歉" class="headerlink" title="错误的道歉"></a>错误的道歉</h3><ul>
<li>逃避责任</li>
<li>讨价还价，好像领导必须原谅你</li>
<li>扑朔迷离，左说一句、右说一句</li>
</ul>
<h3 id="正确的道歉"><a href="#正确的道歉" class="headerlink" title="正确的道歉"></a>正确的道歉</h3><ul>
<li>开门见山，</li>
<li>揣摩内容</li>
<li>方式正确，给领导选择权</li>
</ul>
<h3 id="绩效瓶颈"><a href="#绩效瓶颈" class="headerlink" title="绩效瓶颈"></a>绩效瓶颈</h3><p><strong>绩效瓶颈标准</strong></p>
<ul>
<li>绩效表现恒定</li>
<li>没有提升空间，你和你的领导不适配</li>
<li>对团队丧失兴趣</li>
</ul>
<p><strong>跳槽，增加的是信任成本</strong>，合作时间长的团队。</p>
<p><strong>走出瓶颈</strong></p>
<ul>
<li>主动向上沟通</li>
<li>明确工作规划</li>
<li>向晋升与涨薪发力</li>
</ul>
<h3 id="跳槽时机"><a href="#跳槽时机" class="headerlink" title="跳槽时机"></a>跳槽时机</h3><ul>
<li>组织信任感，团队不适配，沟通少，领导不放心我</li>
<li>工作的激情，对广告兴趣不感兴趣</li>
</ul>
<h3 id="填写绩效考核表事项"><a href="#填写绩效考核表事项" class="headerlink" title="填写绩效考核表事项"></a>填写绩效考核表事项</h3><p><strong>三不要</strong></p>
<ul>
<li>不要居高自傲</li>
<li>不要隐姓埋名，只写了几行</li>
<li>不要夸大事实</li>
</ul>
<p><strong>三步走</strong></p>
<ul>
<li>整理工作<ul>
<li>以流程管理工具为依据，jira数据导出</li>
<li>以代码提交记录为依据</li>
<li>以工作过程笔记为依据</li>
</ul>
</li>
<li>提炼精粹，总结出最好的三条工作，工作内容不是越多越好<ul>
<li>Excel数据分析</li>
<li>统计出整体数据</li>
</ul>
</li>
<li>突出重点，帮他人省力<ul>
<li>结合部门目标分析</li>
<li>结合主管绩效分析</li>
<li>从观者视角出发</li>
<li>要做到“可进可退”</li>
</ul>
</li>
</ul>
<h2 id="突破你的瓶颈"><a href="#突破你的瓶颈" class="headerlink" title="突破你的瓶颈"></a>突破你的瓶颈</h2><h3 id="如何创新持续发展"><a href="#如何创新持续发展" class="headerlink" title="如何创新持续发展"></a>如何创新持续发展</h3><p>TRIZ，核心理论，萃智，俄文缩写，发明问题的解决理论，加快人们创造发明的进程。</p>
<p>矛盾</p>
<ul>
<li><p>物理矛盾，同一个参数具有相反并且合理的需求，带的水杯希望喝的时候大，背的时候小</p>
<p>如何解决物理矛盾</p>
<ul>
<li>矛盾分离</li>
<li>时间、空间、条件和系统</li>
</ul>
</li>
<li><p>技术矛盾，一个参数的改善会引起另一个参数的恶化，是不同参数之间的矛盾</p>
<p><strong>如何解决技术矛盾</strong></p>
<ul>
<li>使用矛盾矩阵</li>
<li>确定横纵参数，获取如何解决</li>
</ul>
</li>
</ul>
<h3 id="凸显本我"><a href="#凸显本我" class="headerlink" title="凸显本我"></a>凸显本我</h3><p><strong>一页简历</strong></p>
<ul>
<li>降低筛选时间成本</li>
<li>突出重点</li>
</ul>
<p><strong>排版风格</strong></p>
<ul>
<li>尽量不贴照片</li>
<li>风格色彩统一</li>
</ul>
<p><strong>项目经验，事不过三</strong></p>
<p><strong>隐藏弱点</strong>，教育弱点放在最后部分</p>
<h3 id="如何提升个人影响力"><a href="#如何提升个人影响力" class="headerlink" title="如何提升个人影响力"></a>如何提升个人影响力</h3><p><strong>你有五年规划吗？</strong></p>
<p>每一年每一个月的规划，近期的每周每天的规划。敢想敢做。</p>
<p><strong>凡富于创造性必敏于模仿，凡不善于模仿的人决不能创造。</strong></p>
<p><strong>影响力提升法则</strong></p>
<ul>
<li>多写：出书、写博客</li>
<li>多说：大中小型演讲</li>
<li>多创造：发明专利，创新项目</li>
</ul>
<h3 id="TRIZ实践"><a href="#TRIZ实践" class="headerlink" title="TRIZ实践"></a>TRIZ实践</h3><p><strong>组合原理</strong></p>
<ul>
<li>将相同的或完成类似操作的物体组合</li>
<li>将时间上相同或类似的操作组合</li>
</ul>
<p><strong>多用性原理</strong></p>
<ul>
<li>同一个物体执行多种不同功能</li>
<li>不再需要借助其他物体</li>
</ul>
<p><strong>嵌套原理</strong></p>
<ul>
<li>一个物体立于另一个物体之内</li>
<li>一个物体通过另一个物体的空腔</li>
</ul>
<p><strong>预先防范原理</strong></p>
<ul>
<li>事先准备好应急手段，abs</li>
<li>增加物体的可靠性</li>
</ul>
<p><strong>动态原理</strong></p>
<ul>
<li>物体的特性变化每个阶段都是最佳</li>
<li>物体分成彼此相对移动部分</li>
</ul>
<p><strong>变害为宝</strong></p>
<ul>
<li>利用有害因素获取有益效果</li>
<li>利用有害因素之间的组合消除有害性</li>
</ul>
<p><strong>复制原理</strong></p>
<ul>
<li>用简单廉价复制品代替昂贵品</li>
<li>用光学拷贝代替物体</li>
</ul>
<h3 id="如何写下你的想法，分享"><a href="#如何写下你的想法，分享" class="headerlink" title="如何写下你的想法，分享"></a>如何写下你的想法，分享</h3><p><strong>写作 Write</strong></p>
<p><strong>出书 Pubish</strong> 打开知名度，提升个人标签，不要功利想法，造福别人。</p>
<p><strong>博客 Blog</strong>，除了技术的blog和美食blog也可以有。</p>
<p><strong>专利 Patent</strong> 敢想。</p>
<h3 id="录下你的想法"><a href="#录下你的想法" class="headerlink" title="录下你的想法"></a>录下你的想法</h3><p><strong>演讲 Speech</strong>，一种精心准备的演讲（即时演讲）</p>
<p><strong>直播 Live</strong>，更多的互动性，即时反馈</p>
<p><strong>公开课 Class</strong>，交流自己的想法和方式，垂直领域有体系化的思路，短视频的出书。</p>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2023/11/25/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8Bddia/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2023/11/25/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8Bddia/" class="post-title-link" itemprop="url">一步一步之ddia</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2023-11-25 23:06:03" itemprop="dateCreated datePublished" datetime="2023-11-25T23:06:03+08:00">2023-11-25</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-12-28 22:24:14" itemprop="dateModified" datetime="2023-12-28T22:24:14+08:00">2023-12-28</time>
              </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>3.2k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="Chapter-1-Reliable-Scalable-and"><a href="#Chapter-1-Reliable-Scalable-and" class="headerlink" title="Chapter 1 Reliable Scalable and"></a>Chapter 1 Reliable Scalable and</h2><h3 id="常见的数据系统"><a href="#常见的数据系统" class="headerlink" title="常见的数据系统"></a>常见的数据系统</h3><ul>
<li>存储数据，以便之后再次使用 - 数据库</li>
<li>记住一些非常 <strong>重</strong>的操作结构，方便之后加速读取速度 - 缓存</li>
<li>允许用户以各种关键字搜索，以各种条件过滤数据 - 搜索引擎</li>
<li>源源不断的产生数据，并发发给其他进程进行处理 - 流式处理</li>
<li>定期处理累积的大量数据 - 批处理</li>
<li>进行消息的转发和分发 - 消息队列</li>
</ul>
<p>ddia 提供了一种典型的数据系统架构 1-1</p>
<p>实际使用系统设计中，存在很多取舍</p>
<ol>
<li>使用何种缓存策略？是旁路还是写穿透？</li>
<li>部分组件机器出现问题时，是保证可用性还是一致性</li>
<li>当机器一时难以恢复，如何保证数据的正确性和完整性</li>
<li>当负载增加时，是增加机器还是提升单机性能</li>
<li>设计对外的api时，是力求简单还是追求强大</li>
</ol>
<p>书中概括三个词 Reliablity （可靠性）、Scalability（可伸缩性）、Maintainablity（可维护性）。</p>
<h3 id="可靠性"><a href="#可靠性" class="headerlink" title="可靠性"></a>可靠性</h3><p>如何衡量</p>
<ul>
<li><p>功能性</p>
<ul>
<li>正常情况下，满足api给出的行为</li>
<li>用户输入/误入操作，能够正常处理</li>
</ul>
</li>
<li><p>性能性</p>
<ul>
<li>给定硬件和数据量下，能够满足承若的性能指标</li>
</ul>
</li>
<li><p>安全上</p>
<p>能够阻止未授权，恶意破坏</p>
</li>
</ul>
<h4 id="故障类型"><a href="#故障类型" class="headerlink" title="故障类型"></a>故障类型</h4><ul>
<li><p>硬件故障</p>
</li>
<li><p>软件错误</p>
</li>
<li><p>人为问题</p>
<ul>
<li><p>设计编码</p>
<ul>
<li>尽可能消除不必要的假说</li>
<li>进程间隔离</li>
<li>服务间熔断设计</li>
</ul>
</li>
<li><p>测试阶段</p>
<ul>
<li>尽可能引入第三方测试，尽量将测试平台自动化</li>
<li>单元测试、集成测试、e2e测试、混沌测试</li>
</ul>
</li>
<li><p>运行阶段</p>
<ul>
<li>详细的仪表盘</li>
<li>持续自检</li>
<li>报警机制</li>
<li>问题预案</li>
</ul>
</li>
<li><p>针对组织</p>
<p>科学的培训和管理</p>
</li>
</ul>
</li>
</ul>
<h3 id="可伸缩性"><a href="#可伸缩性" class="headerlink" title="可伸缩性"></a>可伸缩性</h3><p><strong>只有存活下来的产品才有资格谈伸缩，而过早的伸缩设计往往活不下去</strong></p>
<h4 id="衡量负载"><a href="#衡量负载" class="headerlink" title="衡量负载"></a>衡量负载</h4><p>load parameters(负载参数)</p>
<ul>
<li>应用日活月活</li>
<li>每秒web服务器发出的请求</li>
</ul>
<p>一般来说读多于写，twiiter 中大v发布用户的情况下，常见的处理有推和拉</p>
<ol>
<li>拉，每个人查看首页feed，从数据库拉取所有关注用户推文，合并后展现</li>
<li>推，为每个用户保存一个feed流视图，当用户发推文时，将其插入所有关注者的feed流视图</li>
</ol>
<h4 id="描述性能"><a href="#描述性能" class="headerlink" title="描述性能"></a>描述性能</h4><ol>
<li>吞吐量 throughput</li>
<li>响应时间 response time</li>
<li>延迟 latency</li>
</ol>
<h4 id="应对负载"><a href="#应对负载" class="headerlink" title="应对负载"></a>应对负载</h4><ol>
<li>纵向伸缩或者垂直伸缩：换具有更强大的性能机器。e.g. 大型机器学习训练</li>
<li>横向伸缩或者水平伸缩：并联很多廉价机，分摊负债，e.g. 马斯克造火箭</li>
</ol>
<p>针对不同应用场景：</p>
<p>首先。规模小，尽可能使用性能好一点的机器，省去麻烦</p>
<p>其次，可以上云，利用云的可伸缩性。</p>
<p>最后，实在不行再考虑自行设计可伸缩的分布式架构。</p>
<h3 id="可维护性"><a href="#可维护性" class="headerlink" title="可维护性"></a>可维护性</h3><p>软件整个生命周期来看，维护阶段绝对占大头。大部分人喜欢挖坑，不喜欢填坑。</p>
<ul>
<li>可运维性，运维团队无痛接手</li>
<li>简洁性，便于新手开发平滑上手，<strong>需要一个合理的抽象，并尽量消除各种复杂度，如，层次化抽象</strong></li>
<li>可演化性，便于后面需求快速适配，避免代码绑定在某种实现上，也可称为，可扩展性</li>
</ul>
<h4 id="可运维性"><a href="#可运维性" class="headerlink" title="可运维性"></a>可运维性</h4><p>人生苦短，关爱运维</p>
<ol>
<li>紧盯系统状态，出问题时快速恢复</li>
<li>恢复后，复盘问题，定位原因</li>
<li>定期对平台、库、组件进行更新升级</li>
<li>了解组件相互关系，避免级联故障</li>
<li>建立自动化配置管理、服务管理、更新升级机制</li>
<li>执行复杂维护任务，如将存储系统从一个数据中心搬到另一个数据中心</li>
<li>配置变更时，保证系统安全</li>
</ol>
<p>规范</p>
<ol>
<li>友好的文档和一致的运维规范</li>
<li>细致的监控仪表盘、自检、报警</li>
<li>通用的缺省配置</li>
<li>出问题时的自愈机制、无法自愈时允许管理员手动介入</li>
<li>将维护过程尽可能自动化</li>
<li>避免单点依赖，<strong>无论是机器还是人</strong></li>
</ol>
<h4 id="简洁性"><a href="#简洁性" class="headerlink" title="简洁性"></a>简洁性</h4><p>推荐一本书，A Philosophy of Software Design，讲如何在软件设计中定义、识别和降低复杂度。</p>
<p>复杂度的表现</p>
<ol>
<li>状态空间的膨胀</li>
<li>组件间的强耦合</li>
<li>不一致的术语和命名</li>
<li>为了提升性能的hack</li>
<li><strong>随处可见的补丁 workaround</strong></li>
</ol>
<p>需求很简单，但是不妨碍实现复杂：过多引入 <strong>额外复杂度</strong> ,通常是问题理解的不够本质，写出 <strong>流水账</strong>（没有任何抽象，abstraction）的代码。</p>
<p>如果你为一个问题找到合适的抽象，那么问题就解决了一半，拆分子问题，交互、边界：</p>
<ol>
<li>高级语言隐藏机器码、cpu和系统调用细节</li>
<li>sql隐藏了存储体系、索引结构、查询优化实现细节</li>
</ol>
<p>如何找到合适的抽象</p>
<ol>
<li>从计算机领域常见的抽象中找，比如缓存</li>
<li>从日常生活中常接触的概念找</li>
</ol>
<h4 id="可演化性"><a href="#可演化性" class="headerlink" title="可演化性"></a>可演化性</h4><p>系统需求没有变化，说明行业死了。否则需求一定是不断变。</p>
<p>应对之道：</p>
<ul>
<li>项目管理上，敏捷开发（应用层应对快速迭代）</li>
<li>系统设计上，合理抽象、合理封装、对修改关闭、对扩展开放</li>
</ul>
<h2 id="Chapter2-Data-Models-and-Query-Languages"><a href="#Chapter2-Data-Models-and-Query-Languages" class="headerlink" title="Chapter2 Data Models and Query Languages"></a>Chapter2 Data Models and Query Languages</h2><p>如何分析一个 *<em>数据模型 *</em>:</p>
<ol>
<li>基本考察点：数据基本元素，和元素之间的对应关系（一对多，多对多）</li>
<li>利用几种常用模型比较：关系模型（最流行）、文档模型（树状的），图模型（极大自由）</li>
<li>schema 模式：强Schema（写时约束）；弱Schema（读时解析）</li>
</ol>
<h3 id="关系模型vs文档模型"><a href="#关系模型vs文档模型" class="headerlink" title="关系模型vs文档模型"></a>关系模型vs文档模型</h3><h4 id="关系模型"><a href="#关系模型" class="headerlink" title="关系模型"></a>关系模型</h4><p>常见分类</p>
<ol>
<li>事务型（tp）：银行交易、火车票</li>
<li>分析型（ap）：数据报表、监控表盘</li>
<li>混合型（hap）</li>
</ol>
<blockquote>
<p>明明看起来更像表模型，为什么叫关系模型？</p>
<p>关系 relation说法来自集合论，指的是几个集合的笛卡尔的子集，R (D1*D2*D3)</p>
</blockquote>
<h4 id="NoSQL"><a href="#NoSQL" class="headerlink" title="NoSQL"></a>NoSQL</h4><p>Non-SQL-》Not only SQL，MongoDB、ElasticSearch，诞生的元素</p>
<ol>
<li>处于更大的数据集：更强的伸缩性、更高吞吐量</li>
<li>开源免费的兴起</li>
<li>特化的查询操作：关系数据库难以支持，比如图的多跳分析</li>
<li>表达能力更强：关系模型约束太严</li>
</ol>
<p>面向对象的嵌套性和关系数据库的平铺性</p>
<h4 id="文档模型"><a href="#文档模型" class="headerlink" title="文档模型"></a>文档模型</h4><p>天然的一对多、树形嵌套关系，如简历。</p>
<h4 id="网状模型"><a href="#网状模型" class="headerlink" title="网状模型"></a>网状模型</h4><h4 id="关系模型-1"><a href="#关系模型-1" class="headerlink" title="关系模型"></a>关系模型</h4><h3 id="数据查询语言"><a href="#数据查询语言" class="headerlink" title="数据查询语言"></a>数据查询语言</h3><ul>
<li>声明式语言<ul>
<li>描述控制逻辑而非执行流程</li>
<li>SQL、CSS、XSL</li>
<li>抽象程度高</li>
<li>与实现接耦，可以持续优化查询引擎性能</li>
<li>词法分析-》语法分析-〉语义分析-》生成执行计划-〉执行计划优化</li>
<li>声明式更具有多核潜力，给了更多运行优化空间</li>
</ul>
</li>
<li>命令式语言<ul>
<li>描述命令的执行流程，用一系列语言来不断改变状态</li>
<li>IMS，CODASYL，通用语言如C，C++，JS</li>
<li>与实现耦合较深</li>
<li>词法分析-》语法分析-〉语义分析-》中间代码生成-〉代码优化-》目标代码生成</li>
<li>命令式由于指定了代码执行顺序，编译时优化空间较小</li>
</ul>
</li>
</ul>
<h4 id="MapReduce"><a href="#MapReduce" class="headerlink" title="MapReduce"></a>MapReduce</h4><p>Google 的 Map Reduce 模型</p>
<ol>
<li>借鉴函数式编程</li>
<li>一种相当简单的编程模型，或者说原子的抽象，现在不太够用</li>
<li>但是在大数据处理工具匮乏的蛮荒时代（03以前），谷歌提出这套框架相当有开创性</li>
<li>Mapper Combiner Shuffle and Sort Reducer</li>
</ol>
<h4 id="MongoDb-的-MapReduce模型"><a href="#MongoDb-的-MapReduce模型" class="headerlink" title="MongoDb 的 MapReduce模型"></a>MongoDb 的 MapReduce模型</h4><p>MapReduce 特点</p>
<ol>
<li>要求Map和Reduce 是纯函数，无任何副作用，在任意地点，以任意次序执行多次，对相同的输入都能得到相同的输出，因此容易并发调度</li>
<li>非常底层、但表达能力强大的编程模型。可以基于其实现的sql等高级查询语言，如hive</li>
</ol>
<h2 id="Chapter-3-Storage-and-Retrieval"><a href="#Chapter-3-Storage-and-Retrieval" class="headerlink" title="Chapter 3: Storage and Retrieval"></a>Chapter 3: Storage and Retrieval</h2><p>本章主要聚焦在底层如何查询和存储，这其中，有个逻辑链条：使用场景 -》查询类型-〉存储格式</p>
<p>查询类型主要分为两类</p>
<table>
<thead>
<tr>
<th>引擎类型</th>
<th>请求数量</th>
<th>数据量</th>
<th>存储格式</th>
<th>用户</th>
<th>场景举例</th>
<th>产品举例</th>
</tr>
</thead>
<tbody><tr>
<td>OLTP</td>
<td>相对繁琐，侧重在线交易</td>
<td>总体和单次查询都相对小</td>
<td>多用行存</td>
<td>一般用户</td>
<td>银行交易</td>
<td>mysql</td>
</tr>
<tr>
<td>OLAP</td>
<td>相对较少</td>
<td>总体和单次查询都相对巨大</td>
<td>列存储</td>
<td>商业用户</td>
<td>商业分析</td>
<td>ClickHouse</td>
</tr>
</tbody></table>
<p>写文章的逻辑组织和架构很具有参考意义。</p>
<h3 id="驱动数据库的底层数据结构"><a href="#驱动数据库的底层数据结构" class="headerlink" title="驱动数据库的底层数据结构"></a>驱动数据库的底层数据结构</h3><p>本节由一个shell脚本出发，到一个相当简单但是可用的bitcask，然后引出LSM-Tree，他们都属于日志流范畴，之后转向存储引擎另一个流派-b树，最后探讨了-索引。</p>
<p>分析一下为什么work，也反映了日志结构存储最基本原理：</p>
<ol>
<li>set 在文件末尾追加了一个kv对</li>
<li>get 匹配所有的key，返回最后（也即最新）一条kv对中的value</li>
</ol>
<p>可以看出：写很快，但是读需要全文逐行扫描，会慢很多。典型的以读换写。为了加快读，我们需要构建 <strong>索引</strong> ：一种允许基于某个字段查找的额外数据结构。</p>
<p>索引从原数据中构建，只为加快查找。因此索引会耗费一定额外空间和插入时间（每次插入需要更新索引），即，重新以空间和写换取读。</p>
<h3 id="哈希索引"><a href="#哈希索引" class="headerlink" title="哈希索引"></a>哈希索引</h3><p>内存维护hashMap，key是查询key，value是kv条目的起始位置和长度</p>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2023/11/19/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8Bwebflux/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2023/11/19/%E4%B8%80%E6%AD%A5%E4%B8%80%E6%AD%A5%E4%B9%8Bwebflux/" class="post-title-link" itemprop="url">一步一步之webflux</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2023-11-19 08:33:18" itemprop="dateCreated datePublished" datetime="2023-11-19T08:33:18+08:00">2023-11-19</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-11-26 22:50:35" itemprop="dateModified" datetime="2023-11-26T22:50:35+08:00">2023-11-26</time>
              </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>8.5k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="WebFlux"><a href="#WebFlux" class="headerlink" title="WebFlux"></a>WebFlux</h2><blockquote>
<p>WebFlux 是由 Spring 官方提供的一套 <strong>响应式编程框架</strong>，异步、非阻塞（一个线程处理多个请求）结合Reactive Stream流式编程 <strong>基于netty</strong>，优点是 <strong>能够以固定的线程来处理高并发（充分发挥机器性能）</strong>。查了下Flux的翻译，发现源于法语，意同英语的Flow。</p>
</blockquote>
<h2 id="Reactive-Stream"><a href="#Reactive-Stream" class="headerlink" title="Reactive Stream"></a>Reactive Stream</h2><p>reactive stream 的概念最早由.NET提出，在Netflix 推出 RxJava，本身是一种编程模式，主要是为了解决生产者-消费者模型问题，并于2015年推出 reactive stream规范。jdk官方实现在jdk9引入，将 org.reactivestream的相关定义拷贝到 java.util.cocurrent.Flow下，跟其他技术无耦合，Spring 是流跟响应式一起。</p>
<h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><ul>
<li>背压，发布者和订阅者的互动。sns 发布者发布多少，订阅者接受多少；reactive 可以做到互动，调节数据控制流量，解决发布数据过多，或者订阅者来不及消费的情况<ul>
<li>例子，自来水公司是发布者，家庭是订阅者，之前的模式是水一直流；背压就相当于有水龙头</li>
<li>例子，生产多少手机，销售商卖多少手机；背压，销售商告诉生产商能卖多少</li>
</ul>
</li>
</ul>
<h3 id="接口"><a href="#接口" class="headerlink" title="接口"></a>接口</h3><ul>
<li>Publisher 发布者<ul>
<li>subscribe 产生订阅关系</li>
</ul>
</li>
<li>Subscriber<ul>
<li>onSubScirbe 第一次签署协议</li>
<li>onNext 接受数据</li>
<li>onError 错误</li>
<li>onComplete </li>
</ul>
</li>
<li>Subscrition 签署背压协议，发布者和订阅者实现通信关系<ul>
<li>request </li>
<li>cancel</li>
</ul>
</li>
<li>Procesor 中间处理<ul>
<li>中间角色，过滤器，中转站</li>
</ul>
</li>
</ul>
<p><img src="flux.png" alt=""></p>
<h3 id="demo"><a href="#demo" class="headerlink" title="demo"></a>demo</h3><p>理解响应式流的执行顺序</p>
<ol>
<li>创建发布者和订阅者，分别是Publisher和Subcriber的实例</li>
<li>订阅者调用发布者的subcribe 进行订阅</li>
<li>发布者调用订阅者的onSubscribe传递Subscription</li>
<li>订阅者调用 Subscription 的request 方法请求数据</li>
<li>发布者调用订阅者的onNext方法传递数据给订阅者</li>
<li>数据传递完成后调用订阅者的 onComplete 方法通知完成</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FlowDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="comment">// 1. 定义发布者 发布类型是 Integer</span></span><br><span class="line">        <span class="comment">// 直接使用jdk SubmissionPublisher 它实现了 Publisher 接口</span></span><br><span class="line">        SubmissionPublisher&lt;Integer&gt; publisher = <span class="keyword">new</span> SubmissionPublisher&lt;Integer&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 2. 定义订阅者</span></span><br><span class="line">        Flow.Subscriber&lt;Integer&gt; subscriber = <span class="keyword">new</span> Flow.Subscriber&lt;Integer&gt;() &#123;</span><br><span class="line"></span><br><span class="line">            <span class="comment">/**</span></span><br><span class="line"><span class="comment">             * 订阅关系</span></span><br><span class="line"><span class="comment">             */</span></span><br><span class="line">            <span class="keyword">private</span> Flow.Subscription subscription;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onSubscribe</span><span class="params">(Flow.Subscription subscription)</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 保存订阅关系</span></span><br><span class="line">                <span class="keyword">this</span>.subscription = subscription;</span><br><span class="line">                <span class="comment">// 告诉发布者请求一个数据</span></span><br><span class="line">                <span class="keyword">this</span>.subscription.request(<span class="number">1</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onNext</span><span class="params">(Integer item)</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 接受一个数据，处理</span></span><br><span class="line">                System.out.println(item);</span><br><span class="line">                <span class="comment">// 处理完请求再请求一个数据；【关键步骤】</span></span><br><span class="line">                <span class="keyword">this</span>.subscription.request(<span class="number">1</span>);</span><br><span class="line">                <span class="comment">// 或者已经达到目标了 告诉发布者不再需要数据</span></span><br><span class="line"><span class="comment">//                this.subscription.cancel();</span></span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onError</span><span class="params">(Throwable throwable)</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 出现异常（例如处理数据出现异常）</span></span><br><span class="line">                throwable.printStackTrace();</span><br><span class="line">                <span class="comment">// 可以告诉发布者不需要数据了</span></span><br><span class="line">                <span class="keyword">this</span>.subscription.cancel();</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onComplete</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 数据全部处理完</span></span><br><span class="line">                System.out.println(<span class="string">"处理完"</span>);</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 3. 发布者订阅者建立关系</span></span><br><span class="line">        publisher.subscribe(subscriber);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 4. 生产数据并发布</span></span><br><span class="line">        <span class="keyword">int</span> data = <span class="number">11</span>;</span><br><span class="line">        publisher.submit(data);</span><br><span class="line">        publisher.submit(data);</span><br><span class="line">        publisher.submit(data);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 5. 结束后关闭发布者</span></span><br><span class="line">        <span class="comment">// 正式环境应该放在finally 或者 try-resource</span></span><br><span class="line">        publisher.close();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 主线程延迟停止，否则数据没有消费就退出</span></span><br><span class="line">        Thread.currentThread().join(<span class="number">1000</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="异步-Servlet"><a href="#异步-Servlet" class="headerlink" title="异步 Servlet"></a>异步 Servlet</h2><blockquote>
<p>原理，Servlet3.0 支持异步http请求，同步Servlet阻塞了什么，tomcat容器的servlet线程。服务器后台才有异步，对于前端来说都是同步。</p>
</blockquote>
<h3 id="概念-1"><a href="#概念-1" class="headerlink" title="概念"></a>概念</h3><ul>
<li>同步Servlet阻塞了tomcat 容器的servlet线程，每个请求分配一个处理servlet线程</li>
<li>异步原理，不会阻塞tomcat的servlet线程</li>
</ul>
<p><img src="servlet3.png" alt=""></p>
<h3 id="demo-1"><a href="#demo-1" class="headerlink" title="demo"></a>demo</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.issac.webflux2.servlet;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RestController;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.servlet.AsyncContext;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.AsyncEvent;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.AsyncListener;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletResponse;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: ywy</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span>: 2023-11-26</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@desc</span>:</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@Slf</span>4j</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ServletController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping</span>(<span class="string">"syncTask"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">syncRequest</span><span class="params">(HttpServletRequest request,</span></span></span><br><span class="line"><span class="function"><span class="params">                            HttpServletResponse response)</span> <span class="keyword">throws</span> InterruptedException, IOException </span>&#123;</span><br><span class="line">        log.info(<span class="string">"同步任务开始"</span>);</span><br><span class="line">        Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">        response.setCharacterEncoding(<span class="string">"UTF-8"</span>);</span><br><span class="line">        response.setContentType(<span class="string">"text/html;charset=UTF-8"</span>);</span><br><span class="line">        response.getWriter().println(<span class="string">"同步任务返回"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@RequestMapping</span>(<span class="string">"asyncTask"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">asyncRequest</span><span class="params">(HttpServletRequest request,</span></span></span><br><span class="line"><span class="function"><span class="params">                             HttpServletResponse response)</span> <span class="keyword">throws</span> InterruptedException, IOException </span>&#123;</span><br><span class="line"></span><br><span class="line">        response.setCharacterEncoding(<span class="string">"UTF-8"</span>);</span><br><span class="line">        response.setContentType(<span class="string">"text/html;charset=UTF-8"</span>);</span><br><span class="line">        AsyncContext asyncContext = request.startAsync();</span><br><span class="line">        asyncContext.addListener(<span class="keyword">new</span> AsyncListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onComplete</span><span class="params">(AsyncEvent asyncEvent)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">                log.info(<span class="string">"异步线程完成"</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onTimeout</span><span class="params">(AsyncEvent asyncEvent)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">                log.info(<span class="string">"异步线程超时"</span>);</span><br><span class="line">                asyncEvent.getAsyncContext().getResponse().getWriter().println(<span class="string">"timeout"</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onError</span><span class="params">(AsyncEvent asyncEvent)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">                log.info(<span class="string">"异步线程出错"</span>);</span><br><span class="line">                asyncEvent.getAsyncContext().getResponse().getWriter().println(<span class="string">"异步线程出错"</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onStartAsync</span><span class="params">(AsyncEvent asyncEvent)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">                log.info(<span class="string">"异步线程开始"</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        asyncContext.setTimeout(<span class="number">3000</span>);</span><br><span class="line">        <span class="comment">// start使用默认线程池ForkJoinPool，当然也可以用自定义线程池，调用这个方法后，主线程就结束了</span></span><br><span class="line">        asyncContext.start(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    log.info(<span class="string">"异步任务开始"</span>);</span><br><span class="line">                    Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">                    asyncContext.getResponse().getWriter().println(<span class="string">"异步任务返回"</span>);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (IOException | InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">                log.info(<span class="string">"异步任务完成"</span>);</span><br><span class="line">                asyncContext.complete();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="Spring-Web-Flux"><a href="#Spring-Web-Flux" class="headerlink" title="Spring Web Flux"></a>Spring Web Flux</h2><p>除了api使用，还需要了解工作机制，基础知识储备。</p>
<ul>
<li>概念 非阻塞，运行在netty容器，非阻塞（代表一个线程可以处理多个请求），基于响应式流，异步Servlet容器，关系型不支持</li>
<li>优势  支持非常高的并发量，水平扩展（加人、花更多的钱）、垂直扩展（加班、人还是一个人）</li>
</ul>
<h3 id="Flux"><a href="#Flux" class="headerlink" title="Flux"></a>Flux</h3><ul>
<li>Mono究竟是什么东西？reactor 就是jdk8的stream + jdk9的reactive stream，mono 0-1个元素，flux 0-N个元素</li>
<li>需要指定生产者类型,produce = text/eventStream</li>
<li>flatMap操作数据，并返回Mono，用flatMap，如果不操作数据，知识转换数据，使用map</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FluxDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> InterruptedException </span>&#123;</span><br><span class="line">        <span class="comment">// 创建Flux</span></span><br><span class="line">        Flux&lt;Integer&gt; flux = Flux.range(<span class="number">1</span>, <span class="number">5</span>);</span><br><span class="line">        flux.subscribe(System.out::println);</span><br><span class="line">        <span class="comment">// 创建 Mono</span></span><br><span class="line">        Mono&lt;Integer&gt; mono = Mono.just(<span class="number">1</span>);</span><br><span class="line">        Mono&lt;String&gt; stringMono = mono.map(it -&gt; <span class="string">"处理数据"</span> + it);</span><br><span class="line">        stringMono.subscribe(System.out::println);</span><br><span class="line">        <span class="comment">// 时间间隔</span></span><br><span class="line">        Flux&lt;Long&gt; timeFlux = Flux.interval(Duration.ofMillis(<span class="number">1000</span>));</span><br><span class="line">        timeFlux.subscribe(System.out::println);</span><br><span class="line">        Thread.currentThread().join(<span class="number">60000</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="SSE"><a href="#SSE" class="headerlink" title="SSE"></a>SSE</h3><p>Flux 可以返回多个数据，html5的sse，sse跟异步没什么关系。自动重连</p>
<p><img src="webflux-sse.png" alt=""></p>
<ul>
<li><p>服务端</p>
<p>设置contentType text/event-stream，characterEncoding 必须utf-8，格式是data:+数据+2个回车，flush，也可以指定数据标识</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">WebFluxController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@CrossOrigin</span></span><br><span class="line">    <span class="meta">@RequestMapping</span>(value = <span class="string">"sse"</span>,produces = MediaType.TEXT_EVENT_STREAM_VALUE)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Flux&lt;String&gt; <span class="title">greeting</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> Flux.interval(Duration.ofMillis(<span class="number">1000</span>)).map(it-&gt; UUID.randomUUID().toString());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>客户端，依赖html5</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;meta charset=<span class="string">"UTF-8"</span>&gt;</span><br><span class="line">    &lt;title&gt;Server-sent events demo&lt;<span class="regexp">/title&gt;</span></span><br><span class="line"><span class="regexp">&lt;/</span>head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;button&gt;Close the connection&lt;<span class="regexp">/button&gt;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">&lt;ul&gt;</span></span><br><span class="line"><span class="regexp">&lt;/u</span>l&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">    <span class="keyword">var</span> button = <span class="built_in">document</span>.querySelector(<span class="string">"button"</span>);</span><br><span class="line">    <span class="keyword">var</span> eventList = <span class="built_in">document</span>.querySelector(<span class="string">'ul'</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> evtSource = <span class="keyword">new</span> EventSource(<span class="string">'http://127.0.0.1:8080/sse'</span>);</span><br><span class="line"></span><br><span class="line">    evtSource.onmessage = <span class="function"><span class="keyword">function</span>(<span class="params">e</span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"data:"</span>+e.data);</span><br><span class="line">        <span class="keyword">var</span> newElement = <span class="built_in">document</span>.createElement(<span class="string">"li"</span>);</span><br><span class="line">        newElement.innerHTML = <span class="string">"default data  : "</span> + e.data;</span><br><span class="line">        eventList.appendChild(newElement);</span><br><span class="line">    &#125;;</span><br><span class="line">    evtSource.onopen = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"connection opened"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    evtSource.onerror = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"connection error"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    button.onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">"connnection closed"</span>)</span><br><span class="line">        evtSource.close();</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    evtSource.addEventListener(<span class="string">"ping"</span>, <span class="function"><span class="keyword">function</span>(<span class="params">e</span>) </span>&#123;</span><br><span class="line">        <span class="keyword">var</span> newElement = <span class="built_in">document</span>.createElement(<span class="string">"li"</span>);</span><br><span class="line">        newElement.innerHTML = <span class="string">"ping event data "</span> +e.data;</span><br><span class="line">        eventList.appendChild(newElement);</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">&lt;<span class="regexp">/script&gt;</span></span><br><span class="line"><span class="regexp">&lt;/</span>body&gt;</span><br><span class="line">&lt;<span class="regexp">/html&gt;</span></span><br></pre></td></tr></table></figure>

</li>
</ul>
<h3 id="WebClient"><a href="#WebClient" class="headerlink" title="WebClient"></a>WebClient</h3><p>如何在webflux的环境调用异步接口</p>
<p>spring webflux适合服务间的调用，feign （声明式）、restful</p>
<p>程序 = 数据结构 + 算法</p>
<p>设计最重要的解耦，最关键的设计自己的数据结构+抽象接口；只要有改变的可能，就需要定义接口</p>
<p>instance Of 判断实例</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">EmployeeController</span> </span>&#123;</span><br><span class="line">    <span class="meta">@GetMapping</span>(value = <span class="string">"employees"</span>, produces = MediaType.TEXT_EVENT_STREAM_VALUE)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Flux&lt;Employee&gt; <span class="title">findAll</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> WebClient.create(<span class="string">"localhost:8080/employees"</span>).get().retrieve()</span><br><span class="line">            .bodyToFlux(Employee<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping</span>(value = <span class="string">"web"</span>, produces = MediaType.TEXT_EVENT_STREAM_VALUE)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Flux&lt;Employee&gt; <span class="title">findAllWithWeb</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">long</span> start = System.currentTimeMillis();</span><br><span class="line">        Flux&lt;Employee&gt; employeeFlux = WebClient.create(<span class="string">"localhost:8080/employees2"</span>).get().retrieve()</span><br><span class="line">            .bodyToFlux(Employee<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line">        log.info(<span class="string">"webclient took times:&#123;&#125;"</span>, System.currentTimeMillis() - start);</span><br><span class="line">        <span class="keyword">return</span> employeeFlux;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping</span>(<span class="string">"rest"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;Employee&gt; <span class="title">findWithRestTemplate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">long</span> start = System.currentTimeMillis();</span><br><span class="line">        RestTemplate restTemplate = <span class="keyword">new</span> RestTemplate();</span><br><span class="line">        ResponseEntity&lt;Employee[]&gt; responseEntity = restTemplate.getForEntity(<span class="string">"http://localhost:8080/employees2"</span>, Employee[]<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line">        List&lt;Employee&gt; employees = Arrays.asList(responseEntity.getBody());</span><br><span class="line">        log.info(<span class="string">"restTemplate took times:&#123;&#125;"</span>, System.currentTimeMillis() - start);</span><br><span class="line">        <span class="keyword">return</span> employees;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping</span>(value = <span class="string">"save/&#123;id&#125;/&#123;name&#125;"</span>)</span><br><span class="line">    <span class="function"><span class="keyword">public</span> Mono&lt;Boolean&gt; <span class="title">save</span><span class="params">(@PathVariable Integer id, @PathVariable String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> WebClient.create(<span class="string">"http://localhost:8080/save"</span>)</span><br><span class="line">            .post()</span><br><span class="line">            .body(BodyInserters.fromObject(<span class="keyword">new</span> Employee(id, name)))</span><br><span class="line">            .retrieve()</span><br><span class="line">            .bodyToMono(Boolean<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2023/11/12/%E5%BC%80%E5%8F%91%E6%8A%80%E5%B7%A7/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2023/11/12/%E5%BC%80%E5%8F%91%E6%8A%80%E5%B7%A7/" class="post-title-link" itemprop="url">开发技巧</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2023-11-12 23:04:44 / 修改时间：23:05:06" itemprop="dateCreated datePublished" datetime="2023-11-12T23:04:44+08:00">2023-11-12</time>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>2.9k</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="Person-Skills"><a href="#Person-Skills" class="headerlink" title="Person Skills"></a>Person Skills</h1><p>Why</p>
<ul>
<li>know sth</li>
<li>learn sth</li>
<li>create sth</li>
<li>do sth</li>
</ul>
<p>Where</p>
<ul>
<li>bing</li>
<li>google</li>
</ul>
<p>How</p>
<ul>
<li>“” 增加定位</li>
<li>intitle: 标题</li>
<li>allintitle: 标题多个关键词</li>
<li>incur: 包含网址</li>
<li>intext: 包含关键词</li>
<li>site:cctv.com 限定网站</li>
<li>imagesize 限定图片大小 elon must imageize 240*1440</li>
<li>filetype 限定文件格式</li>
</ul>
<h2 id="open-ai-meeting"><a href="#open-ai-meeting" class="headerlink" title="open ai meeting"></a>open ai meeting</h2><ul>
<li>threading </li>
<li>api assistants </li>
<li>gpts</li>
</ul>
<h3 id="10-best-way-to-improve-code-skills"><a href="#10-best-way-to-improve-code-skills" class="headerlink" title="10 best way to improve code skills"></a>10 best way to improve code skills</h3><ul>
<li>reviewing other’s code </li>
<li>have your code reviewed</li>
<li>slide projects</li>
<li>learn mulipuple languages</li>
<li>open source projects  constribute</li>
<li>reuse code use library</li>
<li>code in front of people</li>
<li>ask for chanllenge projects being uncomfortable from comfortable</li>
</ul>
<p>Next is the answer from chatGPT.</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">To improve your Java coding skills, you can follow these tips:</span><br><span class="line"></span><br><span class="line">1. **Get your basics clear**: Strengthen your basics by finding a good source of knowledge, be it a tutor or online videos or study material. Understanding the basics is a must for further constructing your programming skills ¹.</span><br><span class="line">2. **Read documentation &amp; open-source frameworks source code**: Keep yourself updated about the latest Java technologies by joining some good forums and subscribing to newsletters. Never stop reading. Keep reading about it from somewhere or the other and try and spread your knowledge to others. It’ll also help to maintain your interest in the field. Build a habit to read lots of documentation. May it be specifications, JSR, API documents, tutorials, etc. Reading documents helps you create that essential foundation based on which you program in the best way ¹.</span><br><span class="line">3. **Practice coding**: Implement what you are learning. Practice programming online or offline, that’ll boost your confidence. Be regular, make targets and try and complete them within time. Depth of knowledge comes only when you practically perform what you’ve understood. Join Java Programming Practice and Contest, like CodeChef, Spoj, and Project Euler ¹³.</span><br><span class="line">4. **Group discussions and read books**: Make a group, and have discussions. Join hubs on the internet. Group discussions help you to get different views regarding the topic. You can get the pros and cons of things and you can also solve your doubts over discussions. Also, read standard books and notes ¹.</span><br><span class="line">5. **Subscribe to forums**: When you start working on a new technology the best and first thing to do is to subscribe to technology forums. Whatever the issue you are facing, someone else might have already faced it earlier and you might find the solution. Follow good blogs and also help others by sharing your opinions on them ¹.</span><br><span class="line">6. **Undertake projects**: A good way to improve your coding skills and become a good programmer is to work as a freelancer. It means that you find projects online, work from home, and get paid online, too ¹.</span><br><span class="line"></span><br><span class="line">I hope these tips help you improve your Java coding skills! 😊</span><br><span class="line"></span><br><span class="line">源: 与必应的对话， 2023&#x2F;11&#x2F;11</span><br><span class="line">(1) 7 Tips to Become a Better Java Programmer in 2023. https:&#x2F;&#x2F;www.geeksforgeeks.org&#x2F;how-to-become-a-good-java-programmer&#x2F;.</span><br><span class="line">(2) How to Improve Programming Skills in Java? - HelpToStudy.com. https:&#x2F;&#x2F;www.helptostudy.com&#x2F;how-to-improve-programming-skills-in-java&#x2F;.</span><br><span class="line">(3) How to Code in Java Like a Senior. 7 Ways to Improve the .... https:&#x2F;&#x2F;codegym.cc&#x2F;groups&#x2F;posts&#x2F;520-how-to-code-in-java-like-a-senior-7-ways-to-improve-the-quality-of-your-code.</span><br><span class="line">(4) 15 Important Java Developer Skills (And How To Improve). https:&#x2F;&#x2F;in.indeed.com&#x2F;career-advice&#x2F;career-development&#x2F;java-developer-skills.</span><br></pre></td></tr></table></figure>


      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://issacyoung.cn/2023/10/22/%E4%B8%AA%E4%BA%BA%E6%89%8B%E8%AE%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Issac Young">
      <meta itemprop="description" content="现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Young‘s River">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2023/10/22/%E4%B8%AA%E4%BA%BA%E6%89%8B%E8%AE%B0/" class="post-title-link" itemprop="url">停更两年</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2023-10-22 21:26:54" itemprop="dateCreated datePublished" datetime="2023-10-22T21:26:54+08:00">2023-10-22</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2023-11-05 08:08:18" itemprop="dateModified" datetime="2023-11-05T08:08:18+08:00">2023-11-05</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E4%B8%AA%E4%BA%BA%E6%89%8B%E8%AE%B0/" itemprop="url" rel="index">
                    <span itemprop="name">个人手记</span>
                  </a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="fa fa-file-word-o"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>996</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="停更两年"><a href="#停更两年" class="headerlink" title="停更两年"></a>停更两年</h1><blockquote>
<p>很久没有写点什么，技术上好像也没什么说明的，都是原地打转而已，年岁上倒也快35了，有些担忧，有点信心。这两年住进了新房，也有家庭新成员的到来，生活被逐个填满了，难得有空隙在这里发些牢骚。</p>
</blockquote>
<h2 id="业务项目"><a href="#业务项目" class="headerlink" title="业务项目"></a>业务项目</h2><p>这几年用的开发语言都是java，承接的项目大多也是顶替别人留下的项目持续优化，好在个人的细心程度够，能混口饭吃，言归正传，这两年做的项目大部分是个性化推荐项目，也是从对话项目转推荐的两年。</p>
<p>这一类的项目大部分是贴近用户、贴近业务的，在不断地业务实现的过程中，相比组内其他人而言更为听话，当然也在这两年扑在业务上，少了些技术上的思考，本来上半年还信誓旦旦计划考个【信息系统管理】，因为临了事情耽搁也就扑街了。</p>
<p>以推荐而言，面向用户意味着qps比较大，最大的单服务qps 2万，时不时暴露个线上问题，在反复排查问题的过程中也有了自己的套路。结合k8s、prometheus、elk，排查性能瓶颈，其中抽象业务代码成starter成为个人的一个利器，至少现阶段而言。然而工程上还是被业务牵着鼻子走，如此下去，可替换性还是很大的，除非能持续做同一类业务下去。</p>
<p>前两个月又从推荐转成对话的项目，当然是因为协助低代码开发，之前整理了一套简易的基于【有向无环图】实现的规则引擎，个人认为以此为锚点，可以持续精进。</p>
<h2 id="技术规划"><a href="#技术规划" class="headerlink" title="技术规划"></a>技术规划</h2><p>前几年属于半路转java，跟着慕课的课程学，但这样始终是跟着别人的节奏，需要有自己比较明确的想法。当然，这年头能保住饭碗就不错了，也以为着劳心于业务上面。</p>
<p>之前一直想看完的 《数据库密集系统》每每都看了一两章就搁置了，所以技术规划最好的是跟着工作业务的节奏来。目前自己做的项目的关键词是llm、低代码、langChain，大模型最近一年的热词，就如同之前搞推荐的深度学习一样。作为工程，其实想了解的更多，奈何能力有限，圈子太窄。</p>
<p>jdk已经更新到21了，springboot也升级了3.0，这些都需要与时下同步的，也刚好项目最近需要升级jdk17，结合起来看看。算法这一块几乎无所进展，还是没有摸到门路，说来也工作10年了，那些算法题每每只有需要面试的时候才会突击一下，但是年龄也上来了。未来的敲门砖该是什么？经验？能力？学历？人脉？能看到的眼前，也只有抱紧大腿，跟上节奏，别掉队。</p>
<h2 id="心路历程"><a href="#心路历程" class="headerlink" title="心路历程"></a>心路历程</h2><p>最近几个月，接二连三的事情，也让自己更明白来人世间走一趟的意义，<strong>去感受</strong>。希望自己和身边的人，一步一步往前走。</p>

      
    </div>

    
    
    
<div>
  
</div>
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

  </div>

  
  <nav class="pagination">
    <span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><a class="extend next" rel="next" href="/page/2/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let activeClass = CONFIG.comments.activeClass;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Issac Young"
      src="/images/author.jpg">
  <p class="site-author-name" itemprop="name">Issac Young</p>
  <div class="site-description" itemprop="description">现代生活工作节奏越来越快，需要有时间和空间沉淀积累，将知识点规划成树，记录自己的感悟心得。</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">26</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">19</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/IssacYoung2013" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;IssacYoung2013" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:issacyoung@msn.cn" title="E-Mail → mailto:issacyoung@msn.cn" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

<div class="copyright">
  
  &copy; 2020 – 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Issac Young</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-area-chart"></i>
    </span>
      <span class="post-meta-item-text">站点总字数：</span>
    <span title="站点总字数">64k</span>
</div>


        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

</body>
</html>
<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/clicklove.js"></script>

